<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en"><head>

<meta charset="utf-8">
<meta name="generator" content="quarto-1.7.33">

<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes">


<title>9&nbsp; Build System – Introduction to Zig</title>
<style>
code{white-space: pre-wrap;}
span.smallcaps{font-variant: small-caps;}
div.columns{display: flex; gap: min(4vw, 1.5em);}
div.column{flex: auto; overflow-x: auto;}
div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
ul.task-list{list-style: none;}
ul.task-list li input[type="checkbox"] {
  width: 0.8em;
  margin: 0 0.8em 0.2em -1em; /* quarto-specific, see https://github.com/quarto-dev/quarto-cli/issues/4556 */ 
  vertical-align: middle;
}
/* CSS for syntax highlighting */
html { -webkit-text-size-adjust: 100%; }
pre > code.sourceCode { white-space: pre; position: relative; }
pre > code.sourceCode > span { display: inline-block; line-height: 1.25; }
pre > code.sourceCode > span:empty { height: 1.2em; }
.sourceCode { overflow: visible; }
code.sourceCode > span { color: inherit; text-decoration: inherit; }
div.sourceCode { margin: 1em 0; }
pre.sourceCode { margin: 0; }
@media screen {
div.sourceCode { overflow: auto; }
}
@media print {
pre > code.sourceCode { white-space: pre-wrap; }
pre > code.sourceCode > span { text-indent: -5em; padding-left: 5em; }
}
pre.numberSource code
  { counter-reset: source-line 0; }
pre.numberSource code > span
  { position: relative; left: -4em; counter-increment: source-line; }
pre.numberSource code > span > a:first-child::before
  { content: counter(source-line);
    position: relative; left: -1em; text-align: right; vertical-align: baseline;
    border: none; display: inline-block;
    -webkit-touch-callout: none; -webkit-user-select: none;
    -khtml-user-select: none; -moz-user-select: none;
    -ms-user-select: none; user-select: none;
    padding: 0 4px; width: 4em;
  }
pre.numberSource { margin-left: 3em;  padding-left: 4px; }
div.sourceCode
  {   }
@media screen {
pre > code.sourceCode > span > a:first-child::before { text-decoration: underline; }
}
</style>


<script src="../site_libs/quarto-nav/quarto-nav.js"></script>
<script src="../site_libs/quarto-nav/headroom.min.js"></script>
<script src="../site_libs/clipboard/clipboard.min.js"></script>
<script src="../site_libs/quarto-search/autocomplete.umd.js"></script>
<script src="../site_libs/quarto-search/fuse.min.js"></script>
<script src="../site_libs/quarto-search/quarto-search.js"></script>
<meta name="quarto:offset" content="../">
<link href="../Chapters/09-error-handling.html" rel="next">
<link href="../Chapters/03-unittests.html" rel="prev">
<script src="../site_libs/quarto-html/quarto.js" type="module"></script>
<script src="../site_libs/quarto-html/tabsets/tabsets.js" type="module"></script>
<script src="../site_libs/quarto-html/popper.min.js"></script>
<script src="../site_libs/quarto-html/tippy.umd.min.js"></script>
<script src="../site_libs/quarto-html/anchor.min.js"></script>
<link href="../site_libs/quarto-html/tippy.css" rel="stylesheet">
<link href="../site_libs/quarto-html/quarto-syntax-highlighting-59898bd1c6b9d2bb783127feaa000c76.css" rel="stylesheet" class="quarto-color-scheme" id="quarto-text-highlighting-styles">
<link href="../site_libs/quarto-html/quarto-syntax-highlighting-dark-d329e753491efaeac79c98c4b193a686.css" rel="stylesheet" class="quarto-color-scheme quarto-color-alternate" id="quarto-text-highlighting-styles">
<link href="../site_libs/quarto-html/quarto-syntax-highlighting-59898bd1c6b9d2bb783127feaa000c76.css" rel="stylesheet" class="quarto-color-scheme-extra" id="quarto-text-highlighting-styles">
<script src="../site_libs/bootstrap/bootstrap.min.js"></script>
<link href="../site_libs/bootstrap/bootstrap-icons.css" rel="stylesheet">
<link href="../site_libs/bootstrap/bootstrap-5a7d69291c2a8c67bc3a157f4354e263.min.css" rel="stylesheet" append-hash="true" class="quarto-color-scheme" id="quarto-bootstrap" data-mode="light">
<link href="../site_libs/bootstrap/bootstrap-dark-a459d9a911ec262923466a12d18bc01e.min.css" rel="stylesheet" append-hash="true" class="quarto-color-scheme quarto-color-alternate" id="quarto-bootstrap" data-mode="dark">
<link href="../site_libs/bootstrap/bootstrap-5a7d69291c2a8c67bc3a157f4354e263.min.css" rel="stylesheet" append-hash="true" class="quarto-color-scheme-extra" id="quarto-bootstrap" data-mode="light">
<script id="quarto-search-options" type="application/json">{
  "location": "sidebar",
  "copy-button": false,
  "collapse-after": 3,
  "panel-placement": "start",
  "type": "textbox",
  "limit": 50,
  "keyboard-shortcut": [
    "f",
    "/",
    "s"
  ],
  "show-item-context": false,
  "language": {
    "search-no-results-text": "No results",
    "search-matching-documents-text": "matching documents",
    "search-copy-link-title": "Copy link to search",
    "search-hide-matches-text": "Hide additional matches",
    "search-more-match-text": "more match in this document",
    "search-more-matches-text": "more matches in this document",
    "search-clear-button-title": "Clear",
    "search-text-placeholder": "",
    "search-detached-cancel-button-title": "Cancel",
    "search-submit-button-title": "Submit",
    "search-label": "Search"
  }
}</script>
<script async="" src="https://www.googletagmanager.com/gtag/js?id=G-6CHJXK4CEV"></script>

<script type="text/javascript">

window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
gtag('config', 'G-6CHJXK4CEV', { 'anonymize_ip': true});
</script>


</head>

<body class="nav-sidebar floating quarto-light"><script id="quarto-html-before-body" type="application/javascript">
    const toggleBodyColorMode = (bsSheetEl) => {
      const mode = bsSheetEl.getAttribute("data-mode");
      const bodyEl = window.document.querySelector("body");
      if (mode === "dark") {
        bodyEl.classList.add("quarto-dark");
        bodyEl.classList.remove("quarto-light");
      } else {
        bodyEl.classList.add("quarto-light");
        bodyEl.classList.remove("quarto-dark");
      }
    }
    const toggleBodyColorPrimary = () => {
      const bsSheetEl = window.document.querySelector("link#quarto-bootstrap:not([rel=disabled-stylesheet])");
      if (bsSheetEl) {
        toggleBodyColorMode(bsSheetEl);
      }
    }
    const setColorSchemeToggle = (alternate) => {
      const toggles = window.document.querySelectorAll('.quarto-color-scheme-toggle');
      for (let i=0; i < toggles.length; i++) {
        const toggle = toggles[i];
        if (toggle) {
          if (alternate) {
            toggle.classList.add("alternate");
          } else {
            toggle.classList.remove("alternate");
          }
        }
      }
    };
    const toggleColorMode = (alternate) => {
      // Switch the stylesheets
      const primaryStylesheets = window.document.querySelectorAll('link.quarto-color-scheme:not(.quarto-color-alternate)');
      const alternateStylesheets = window.document.querySelectorAll('link.quarto-color-scheme.quarto-color-alternate');
      manageTransitions('#quarto-margin-sidebar .nav-link', false);
      if (alternate) {
        // note: dark is layered on light, we don't disable primary!
        enableStylesheet(alternateStylesheets);
        for (const sheetNode of alternateStylesheets) {
          if (sheetNode.id === "quarto-bootstrap") {
            toggleBodyColorMode(sheetNode);
          }
        }
      } else {
        disableStylesheet(alternateStylesheets);
        enableStylesheet(primaryStylesheets)
        toggleBodyColorPrimary();
      }
      manageTransitions('#quarto-margin-sidebar .nav-link', true);
      // Switch the toggles
      setColorSchemeToggle(alternate)
      // Hack to workaround the fact that safari doesn't
      // properly recolor the scrollbar when toggling (#1455)
      if (navigator.userAgent.indexOf('Safari') > 0 && navigator.userAgent.indexOf('Chrome') == -1) {
        manageTransitions("body", false);
        window.scrollTo(0, 1);
        setTimeout(() => {
          window.scrollTo(0, 0);
          manageTransitions("body", true);
        }, 40);
      }
    }
    const disableStylesheet = (stylesheets) => {
      for (let i=0; i < stylesheets.length; i++) {
        const stylesheet = stylesheets[i];
        stylesheet.rel = 'disabled-stylesheet';
      }
    }
    const enableStylesheet = (stylesheets) => {
      for (let i=0; i < stylesheets.length; i++) {
        const stylesheet = stylesheets[i];
        if(stylesheet.rel !== 'stylesheet') { // for Chrome, which will still FOUC without this check
          stylesheet.rel = 'stylesheet';
        }
      }
    }
    const manageTransitions = (selector, allowTransitions) => {
      const els = window.document.querySelectorAll(selector);
      for (let i=0; i < els.length; i++) {
        const el = els[i];
        if (allowTransitions) {
          el.classList.remove('notransition');
        } else {
          el.classList.add('notransition');
        }
      }
    }
    const isFileUrl = () => {
      return window.location.protocol === 'file:';
    }
    const hasAlternateSentinel = () => {
      let styleSentinel = getColorSchemeSentinel();
      if (styleSentinel !== null) {
        return styleSentinel === "alternate";
      } else {
        return false;
      }
    }
    const setStyleSentinel = (alternate) => {
      const value = alternate ? "alternate" : "default";
      if (!isFileUrl()) {
        window.localStorage.setItem("quarto-color-scheme", value);
      } else {
        localAlternateSentinel = value;
      }
    }
    const getColorSchemeSentinel = () => {
      if (!isFileUrl()) {
        const storageValue = window.localStorage.getItem("quarto-color-scheme");
        return storageValue != null ? storageValue : localAlternateSentinel;
      } else {
        return localAlternateSentinel;
      }
    }
    const toggleGiscusIfUsed = (isAlternate, darkModeDefault) => {
      const baseTheme = document.querySelector('#giscus-base-theme')?.value ?? 'light';
      const alternateTheme = document.querySelector('#giscus-alt-theme')?.value ?? 'dark';
      let newTheme = '';
      if(authorPrefersDark) {
        newTheme = isAlternate ? baseTheme : alternateTheme;
      } else {
        newTheme = isAlternate ? alternateTheme : baseTheme;
      }
      const changeGiscusTheme = () => {
        // From: https://github.com/giscus/giscus/issues/336
        const sendMessage = (message) => {
          const iframe = document.querySelector('iframe.giscus-frame');
          if (!iframe) return;
          iframe.contentWindow.postMessage({ giscus: message }, 'https://giscus.app');
        }
        sendMessage({
          setConfig: {
            theme: newTheme
          }
        });
      }
      const isGiscussLoaded = window.document.querySelector('iframe.giscus-frame') !== null;
      if (isGiscussLoaded) {
        changeGiscusTheme();
      }
    };
    const authorPrefersDark = false;
    const darkModeDefault = authorPrefersDark;
      document.querySelector('link#quarto-text-highlighting-styles.quarto-color-scheme-extra').rel = 'disabled-stylesheet';
      document.querySelector('link#quarto-bootstrap.quarto-color-scheme-extra').rel = 'disabled-stylesheet';
    let localAlternateSentinel = darkModeDefault ? 'alternate' : 'default';
    // Dark / light mode switch
    window.quartoToggleColorScheme = () => {
      // Read the current dark / light value
      let toAlternate = !hasAlternateSentinel();
      toggleColorMode(toAlternate);
      setStyleSentinel(toAlternate);
      toggleGiscusIfUsed(toAlternate, darkModeDefault);
      window.dispatchEvent(new Event('resize'));
    };
    // Switch to dark mode if need be
    if (hasAlternateSentinel()) {
      toggleColorMode(true);
    } else {
      toggleColorMode(false);
    }
  </script>

<div id="quarto-search-results"></div>
  <header id="quarto-header" class="headroom fixed-top">
  <nav class="quarto-secondary-nav">
    <div class="container-fluid d-flex">
      <button type="button" class="quarto-btn-toggle btn" data-bs-toggle="collapse" role="button" data-bs-target=".quarto-sidebar-collapse-item" aria-controls="quarto-sidebar" aria-expanded="false" aria-label="Toggle sidebar navigation" onclick="if (window.quartoToggleHeadroom) { window.quartoToggleHeadroom(); }">
        <i class="bi bi-layout-text-sidebar-reverse"></i>
      </button>
        <nav class="quarto-page-breadcrumbs" aria-label="breadcrumb"><ol class="breadcrumb"><li class="breadcrumb-item"><a href="../Chapters/07-build-system.html"><span class="chapter-number">9</span>&nbsp; <span class="chapter-title">Build System</span></a></li></ol></nav>
        <a class="flex-grow-1" role="navigation" data-bs-toggle="collapse" data-bs-target=".quarto-sidebar-collapse-item" aria-controls="quarto-sidebar" aria-expanded="false" aria-label="Toggle sidebar navigation" onclick="if (window.quartoToggleHeadroom) { window.quartoToggleHeadroom(); }">      
        </a>
      <button type="button" class="btn quarto-search-button" aria-label="Search" onclick="window.quartoOpenSearch();">
        <i class="bi bi-search"></i>
      </button>
    </div>
  </nav>
</header>
<!-- content -->
<div id="quarto-content" class="quarto-container page-columns page-rows-contents page-layout-article">
<!-- sidebar -->
  <nav id="quarto-sidebar" class="sidebar collapse collapse-horizontal quarto-sidebar-collapse-item sidebar-navigation floating overflow-auto">
    <div class="pt-lg-2 mt-2 text-left sidebar-header">
    <div class="sidebar-title mb-0 py-0">
      <a href="../">Introduction to Zig</a> 
        <div class="sidebar-tools-main">
  <a href="" class="quarto-color-scheme-toggle quarto-navigation-tool  px-1" onclick="window.quartoToggleColorScheme(); return false;" title="Toggle dark mode"><i class="bi"></i></a>
</div>
    </div>
      </div>
        <div class="mt-2 flex-shrink-0 align-items-center">
        <div class="sidebar-search">
        <div id="quarto-search" class="" title="Search"></div>
        </div>
        </div>
    <div class="sidebar-menu-container"> 
    <ul class="list-unstyled mt-1">
        <li class="sidebar-item">
  <div class="sidebar-item-container"> 
  <a href="../index.html" class="sidebar-item-text sidebar-link">
 <span class="menu-text">Welcome</span></a>
  </div>
</li>
        <li class="sidebar-item">
  <div class="sidebar-item-container"> 
  <a href="../Chapters/01-zig-weird.html" class="sidebar-item-text sidebar-link">
 <span class="menu-text"><span class="chapter-number">1</span>&nbsp; <span class="chapter-title">Introducing Zig</span></span></a>
  </div>
</li>
        <li class="sidebar-item">
  <div class="sidebar-item-container"> 
  <a href="../Chapters/03-structs.html" class="sidebar-item-text sidebar-link">
 <span class="menu-text"><span class="chapter-number">2</span>&nbsp; <span class="chapter-title">Control flow, structs, modules and types</span></span></a>
  </div>
</li>
        <li class="sidebar-item">
  <div class="sidebar-item-container"> 
  <a href="../Chapters/01-memory.html" class="sidebar-item-text sidebar-link">
 <span class="menu-text"><span class="chapter-number">3</span>&nbsp; <span class="chapter-title">Memory and Allocators</span></span></a>
  </div>
</li>
        <li class="sidebar-item">
  <div class="sidebar-item-container"> 
  <a href="../Chapters/01-base64.html" class="sidebar-item-text sidebar-link">
 <span class="menu-text"><span class="chapter-number">4</span>&nbsp; <span class="chapter-title">Project 1 - Building a base64 encoder/decoder</span></span></a>
  </div>
</li>
        <li class="sidebar-item">
  <div class="sidebar-item-container"> 
  <a href="../Chapters/02-debugging.html" class="sidebar-item-text sidebar-link">
 <span class="menu-text"><span class="chapter-number">5</span>&nbsp; <span class="chapter-title">Debugging Zig applications</span></span></a>
  </div>
</li>
        <li class="sidebar-item">
  <div class="sidebar-item-container"> 
  <a href="../Chapters/05-pointers.html" class="sidebar-item-text sidebar-link">
 <span class="menu-text"><span class="chapter-number">6</span>&nbsp; <span class="chapter-title">Pointers and Optionals</span></span></a>
  </div>
</li>
        <li class="sidebar-item">
  <div class="sidebar-item-container"> 
  <a href="../Chapters/04-http-server.html" class="sidebar-item-text sidebar-link">
 <span class="menu-text"><span class="chapter-number">7</span>&nbsp; <span class="chapter-title">Project 2 - Building a HTTP Server from scratch</span></span></a>
  </div>
</li>
        <li class="sidebar-item">
  <div class="sidebar-item-container"> 
  <a href="../Chapters/03-unittests.html" class="sidebar-item-text sidebar-link">
 <span class="menu-text"><span class="chapter-number">8</span>&nbsp; <span class="chapter-title">Unit tests</span></span></a>
  </div>
</li>
        <li class="sidebar-item">
  <div class="sidebar-item-container"> 
  <a href="../Chapters/07-build-system.html" class="sidebar-item-text sidebar-link active">
 <span class="menu-text"><span class="chapter-number">9</span>&nbsp; <span class="chapter-title">Build System</span></span></a>
  </div>
</li>
        <li class="sidebar-item">
  <div class="sidebar-item-container"> 
  <a href="../Chapters/09-error-handling.html" class="sidebar-item-text sidebar-link">
 <span class="menu-text"><span class="chapter-number">10</span>&nbsp; <span class="chapter-title">Error handling and unions</span></span></a>
  </div>
</li>
        <li class="sidebar-item">
  <div class="sidebar-item-container"> 
  <a href="../Chapters/09-data-structures.html" class="sidebar-item-text sidebar-link">
 <span class="menu-text"><span class="chapter-number">11</span>&nbsp; <span class="chapter-title">Data Structures</span></span></a>
  </div>
</li>
        <li class="sidebar-item">
  <div class="sidebar-item-container"> 
  <a href="../Chapters/10-stack-project.html" class="sidebar-item-text sidebar-link">
 <span class="menu-text"><span class="chapter-number">12</span>&nbsp; <span class="chapter-title">Project 3 - Building a stack data structure</span></span></a>
  </div>
</li>
        <li class="sidebar-item">
  <div class="sidebar-item-container"> 
  <a href="../Chapters/12-file-op.html" class="sidebar-item-text sidebar-link">
 <span class="menu-text"><span class="chapter-number">13</span>&nbsp; <span class="chapter-title">Filesystem and Input/Output (IO)</span></span></a>
  </div>
</li>
        <li class="sidebar-item">
  <div class="sidebar-item-container"> 
  <a href="../Chapters/14-zig-c-interop.html" class="sidebar-item-text sidebar-link">
 <span class="menu-text"><span class="chapter-number">14</span>&nbsp; <span class="chapter-title">Zig interoperability with C</span></span></a>
  </div>
</li>
        <li class="sidebar-item">
  <div class="sidebar-item-container"> 
  <a href="../Chapters/13-image-filter.html" class="sidebar-item-text sidebar-link">
 <span class="menu-text"><span class="chapter-number">15</span>&nbsp; <span class="chapter-title">Project 4 - Developing an image filter</span></span></a>
  </div>
</li>
        <li class="sidebar-item">
  <div class="sidebar-item-container"> 
  <a href="../Chapters/14-threads.html" class="sidebar-item-text sidebar-link">
 <span class="menu-text"><span class="chapter-number">16</span>&nbsp; <span class="chapter-title">Introducing threads and parallelism in Zig</span></span></a>
  </div>
</li>
        <li class="sidebar-item">
  <div class="sidebar-item-container"> 
  <a href="../Chapters/15-vectors.html" class="sidebar-item-text sidebar-link">
 <span class="menu-text"><span class="chapter-number">17</span>&nbsp; <span class="chapter-title">Introducing Vectors and SIMD</span></span></a>
  </div>
</li>
        <li class="sidebar-item">
  <div class="sidebar-item-container"> 
  <a href="../Chapters/references.html" class="sidebar-item-text sidebar-link">
 <span class="menu-text">References</span></a>
  </div>
</li>
    </ul>
    </div>
</nav>
<div id="quarto-sidebar-glass" class="quarto-sidebar-collapse-item" data-bs-toggle="collapse" data-bs-target=".quarto-sidebar-collapse-item"></div>
<!-- margin-sidebar -->
    <div id="quarto-margin-sidebar" class="sidebar margin-sidebar">
        <nav id="TOC" role="doc-toc" class="toc-active">
    <h2 id="toc-title">Table of contents</h2>
   
  <ul>
  <li><a href="#how-source-code-is-built" id="toc-how-source-code-is-built" class="nav-link active" data-scroll-target="#how-source-code-is-built"><span class="header-section-number">9.1</span> How source code is built?</a></li>
  <li><a href="#sec-build-fun" id="toc-sec-build-fun" class="nav-link" data-scroll-target="#sec-build-fun"><span class="header-section-number">9.2</span> The <code>build()</code> function</a></li>
  <li><a href="#sec-targets" id="toc-sec-targets" class="nav-link" data-scroll-target="#sec-targets"><span class="header-section-number">9.3</span> Target objects</a></li>
  <li><a href="#setting-the-build-mode" id="toc-setting-the-build-mode" class="nav-link" data-scroll-target="#setting-the-build-mode"><span class="header-section-number">9.4</span> Setting the build mode</a></li>
  <li><a href="#setting-the-version-of-your-build" id="toc-setting-the-version-of-your-build" class="nav-link" data-scroll-target="#setting-the-version-of-your-build"><span class="header-section-number">9.5</span> Setting the version of your build</a></li>
  <li><a href="#sec-detect-os" id="toc-sec-detect-os" class="nav-link" data-scroll-target="#sec-detect-os"><span class="header-section-number">9.6</span> Detecting the OS in your build script</a></li>
  <li><a href="#adding-a-run-step-to-your-build-process" id="toc-adding-a-run-step-to-your-build-process" class="nav-link" data-scroll-target="#adding-a-run-step-to-your-build-process"><span class="header-section-number">9.7</span> Adding a run step to your build process</a></li>
  <li><a href="#build-unit-tests-in-your-project" id="toc-build-unit-tests-in-your-project" class="nav-link" data-scroll-target="#build-unit-tests-in-your-project"><span class="header-section-number">9.8</span> Build unit tests in your project</a></li>
  <li><a href="#tailoring-your-build-process-with-user-provided-options" id="toc-tailoring-your-build-process-with-user-provided-options" class="nav-link" data-scroll-target="#tailoring-your-build-process-with-user-provided-options"><span class="header-section-number">9.9</span> Tailoring your build process with user-provided options</a></li>
  <li><a href="#linking-to-external-libraries" id="toc-linking-to-external-libraries" class="nav-link" data-scroll-target="#linking-to-external-libraries"><span class="header-section-number">9.10</span> Linking to external libraries</a></li>
  <li><a href="#sec-building-c-code" id="toc-sec-building-c-code" class="nav-link" data-scroll-target="#sec-building-c-code"><span class="header-section-number">9.11</span> Building C code</a>
  <ul class="collapse">
  <li><a href="#creating-c-compiler-flags" id="toc-creating-c-compiler-flags" class="nav-link" data-scroll-target="#creating-c-compiler-flags"><span class="header-section-number">9.11.1</span> Creating C compiler flags</a></li>
  <li><a href="#listing-your-c-files" id="toc-listing-your-c-files" class="nav-link" data-scroll-target="#listing-your-c-files"><span class="header-section-number">9.11.2</span> Listing your C files</a></li>
  <li><a href="#defining-c-macros" id="toc-defining-c-macros" class="nav-link" data-scroll-target="#defining-c-macros"><span class="header-section-number">9.11.3</span> Defining C Macros</a></li>
  <li><a href="#sec-library-paths" id="toc-sec-library-paths" class="nav-link" data-scroll-target="#sec-library-paths"><span class="header-section-number">9.11.4</span> Adding library paths</a></li>
  <li><a href="#sec-include-paths" id="toc-sec-include-paths" class="nav-link" data-scroll-target="#sec-include-paths"><span class="header-section-number">9.11.5</span> Adding include paths</a></li>
  </ul></li>
  </ul>
</nav>
    </div>
<!-- main -->
<main class="content" id="quarto-document-content">


<header id="title-block-header" class="quarto-title-block default">
<div class="quarto-title">
<h1 class="title"><span id="sec-build-system" class="quarto-section-identifier"><span class="chapter-number">9</span>&nbsp; <span class="chapter-title">Build System</span></span></h1>
</div>



<div class="quarto-title-meta">

    
  
    
  </div>
  


</header>


<p>In this chapter, we are going to talk about the build system, and how an entire project is built in Zig. One key advantage of Zig is that it includes a build system embedded in the language itself. This is great, because then you do not have to depend on an external system, separated from the compiler, to build your code.</p>
<p>You can find a good description of Zig’s build system in the <a href="https://ziglang.org/learn/build-system/#user-provided-options">article entitled “Build System”</a><a href="#fn1" class="footnote-ref" id="fnref1" role="doc-noteref"><sup>1</sup></a> from the official Zig’s website. We also have the excellent <a href="https://zig.news/xq/zig-build-explained-part-1-59lf">series of posts written by Felix</a><a href="#fn2" class="footnote-ref" id="fnref2" role="doc-noteref"><sup>2</sup></a>. Hence, this chapter represents an extra resource for you to consult and rely on.</p>
<p>Building code is one of the things that Zig is best at. One thing that is particularly difficult in C/C++ and even in Rust, is to cross-compile source code to multiple targets (e.g.&nbsp;multiple computer architectures and operating systems), and the <code>zig</code> compiler is known for being one of the best existing pieces of software for this particular task.</p>
<section id="how-source-code-is-built" class="level2" data-number="9.1">
<h2 data-number="9.1" class="anchored" data-anchor-id="how-source-code-is-built"><span class="header-section-number">9.1</span> How source code is built?</h2>
<p>We already have talked about the challenges of building source code in low-level languages in <a href="01-zig-weird.html#sec-project-files" class="quarto-xref"><span>Section 1.2.1</span></a>. As we described at that section, programmers invented Build Systems to surpass these challenges on the process of building source code in low-level languages.</p>
<p>Low-level languages uses a compiler to compile (or to build) your source code into binary instructions. In C and C++, we normally use compilers like <code>gcc</code>, <code>g++</code> or <code>clang</code> to compile our C and C++ source code into these instructions. Every language have its own compiler, and this is no different in Zig.</p>
<p>In Zig, we have the <code>zig</code> compiler to compile our Zig source code into binary instructions that can be executed by our computer. In Zig, the compilation (or the build) process involves the following components:</p>
<ul>
<li>The Zig modules that contains your source code;</li>
<li>Library files (either a dynamic library or a static library);</li>
<li>Compiler flags that tailors the build process to your needs.</li>
</ul>
<p>These are the things that you need to connect together in order to build your source code in Zig. In C and C++, you would have an extra component, which are the header files of the libraries that you are using. But header files do not exist in Zig, so, you only need to care about them if you are linking your Zig source code with a C library. If that is not your case, you can forget about it.</p>
<p>Your build process is usually organized in a build script. In Zig, we normally write this build script into a Zig module in the root directory of our project, named as <code>build.zig</code>. You write this build script, then, when you run it, your project gets built into binary files that you can use and distribute to your users.</p>
<p>This build script is normally organized around <em>target objects</em>. A target is simply something to be built, or, in other words, it’s something that you want the <code>zig</code> compiler to build for you. This concept of “targets” is present in most Build Systems, especially in CMake<a href="#fn3" class="footnote-ref" id="fnref3" role="doc-noteref"><sup>3</sup></a>.</p>
<p>There are four types of target objects that you can build in Zig, which are:</p>
<ul>
<li>An executable (e.g.&nbsp;a <code>.exe</code> file on Windows).</li>
<li>A shared library (e.g.&nbsp;a <code>.so</code> file in Linux or a <code>.dll</code> file on Windows).</li>
<li>A static library (e.g.&nbsp;a <code>.a</code> file in Linux or a <code>.lib</code> file on Windows).</li>
<li>An executable file that executes only unit tests (or, a “unit tests executable”).</li>
</ul>
<p>We are going to talk more about these target objects in <a href="#sec-targets" class="quarto-xref"><span>Section 9.3</span></a>.</p>
</section>
<section id="sec-build-fun" class="level2" data-number="9.2">
<h2 data-number="9.2" class="anchored" data-anchor-id="sec-build-fun"><span class="header-section-number">9.2</span> The <code>build()</code> function</h2>
<p>A build script in Zig always contains a public (and top-level) <code>build()</code> function declared. It’s like the <code>main()</code> function in the main Zig module of your project, that we discussed in <a href="01-zig-weird.html#sec-main-file" class="quarto-xref"><span>Section 1.2.3</span></a>. But instead of creating the entrypoint to your code, this <code>build()</code> function is the entrypoint to the build process.</p>
<p>This <code>build()</code> function should accept a pointer to a <code>Build</code> object as input, and it should use this “build object” to perform the necessary steps to build your project. The return type of this function is always <code>void</code>, and this <code>Build</code> struct comes directly from the Zig Standard Library (<code>std.Build</code>). So, you can access this struct by just importing the Zig Standard Library into your <code>build.zig</code> module.</p>
<p>Just as a very simple example, here you can see the source code necessary to build an executable file from the <code>hello.zig</code> Zig module.</p>
<div class="cell">
<div class="sourceCode cell-code" id="cb1"><pre class="sourceCode zig code-with-copy"><code class="sourceCode zig"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="kw">const</span> std = <span class="bu">@import</span>(<span class="st">"std"</span>);</span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a><span class="kw">pub</span> <span class="kw">fn</span> build(b: *std.Build) <span class="dt">void</span> <span class="op">{</span></span>
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a>    <span class="kw">const</span> exe = b.addExecutable(.<span class="op">{</span></span>
<span id="cb1-4"><a href="#cb1-4" aria-hidden="true" tabindex="-1"></a>        .name = <span class="st">"hello"</span>,</span>
<span id="cb1-5"><a href="#cb1-5" aria-hidden="true" tabindex="-1"></a>        .root_module = b.createModule(.<span class="op">{</span></span>
<span id="cb1-6"><a href="#cb1-6" aria-hidden="true" tabindex="-1"></a>            .root_source_file = b.path(<span class="st">"hello.zig"</span>),</span>
<span id="cb1-7"><a href="#cb1-7" aria-hidden="true" tabindex="-1"></a>            .target = b.graph.host</span>
<span id="cb1-8"><a href="#cb1-8" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span>)</span>
<span id="cb1-9"><a href="#cb1-9" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span>);</span>
<span id="cb1-10"><a href="#cb1-10" aria-hidden="true" tabindex="-1"></a>    b.installArtifact(exe);</span>
<span id="cb1-11"><a href="#cb1-11" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
</div>
<p>You can define and use other functions and objects in this build script. You can also import other Zig modules as you would normally do in any other module of your project. The only real requirement for this build script, is to have a public and top-level <code>build()</code> function defined, that accepts a pointer to a <code>Build</code> struct as input.</p>
</section>
<section id="sec-targets" class="level2" data-number="9.3">
<h2 data-number="9.3" class="anchored" data-anchor-id="sec-targets"><span class="header-section-number">9.3</span> Target objects</h2>
<p>As we described over the previous sections, a build script is composed around target objects. Each target object is normally a binary file (or an output) that you want to get from the build process. You can list multiple target objects in your build script, so that the build process generates multiple binary files for you at once.</p>
<p>For example, maybe you are a developer working in a cross-platform application, and, because this application is cross-platform, you probably need to release binary files of your software for each OS supported by your application to your end users. Thus, you can define a different target object in your build script for each OS (Windows, Linux, etc.) where you want to publish your software. This will make the <code>zig</code> compiler to build your project to multiple target OS’s at once. The Zig Build System official documentation have a <a href="https://ziglang.org/learn/build-system/#handy-examples">great code example that demonstrates this strategy</a><a href="#fn4" class="footnote-ref" id="fnref4" role="doc-noteref"><sup>4</sup></a>.</p>
<p>A target object is created by the following methods of the <code>Build</code> struct that we introduced in <a href="#sec-build-fun" class="quarto-xref"><span>Section 9.2</span></a>:</p>
<ul>
<li><code>addExecutable()</code> creates an executable file;</li>
<li><code>addSharedLibrary()</code> creates a shared library file;</li>
<li><code>addStaticLibrary()</code> creates a static library file;</li>
<li><code>addTest()</code> creates an executable file that executes unit tests.</li>
</ul>
<p>These functions are methods from the <code>Build</code> struct that you receive as input of the <code>build()</code> function. All of them, create as output a <code>Compile</code> object, which represents a target object to be compiled by the <code>zig</code> compiler. All of these functions accept a similar struct literal as input. This struct literal defines two essential specs about this target object that you are building: <code>name</code>, <code>root_module</code>.</p>
<p>We have already seen these two options being used on the previous example, where we used the <code>addExecutable()</code> method to create an executable target object. This example is reproduced below. Notice the use of the <code>path()</code> method from the <code>Build</code> struct, to define the path to our Zig module in the <code>root_module</code> option.</p>
<div class="cell">
<div class="sourceCode cell-code" id="cb2"><pre class="sourceCode zig code-with-copy"><code class="sourceCode zig"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true" tabindex="-1"></a><span class="kw">const</span> exe = b.addExecutable(.<span class="op">{</span></span>
<span id="cb2-2"><a href="#cb2-2" aria-hidden="true" tabindex="-1"></a>    .name = <span class="st">"hello"</span>,</span>
<span id="cb2-3"><a href="#cb2-3" aria-hidden="true" tabindex="-1"></a>    .root_module = b.createModule(.<span class="op">{</span></span>
<span id="cb2-4"><a href="#cb2-4" aria-hidden="true" tabindex="-1"></a>        .root_source_file = b.path(<span class="st">"hello.zig"</span>),</span>
<span id="cb2-5"><a href="#cb2-5" aria-hidden="true" tabindex="-1"></a>        .target = b.graph.host</span>
<span id="cb2-6"><a href="#cb2-6" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span>)</span>
<span id="cb2-7"><a href="#cb2-7" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>);</span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
</div>
<p>The <code>name</code> option specify the name that you want to give to the binary file defined by this target object. So, in this example, we are building an executable file named <code>hello</code>. It’s common to set this <code>name</code> option to the name of your project.</p>
<p>Furthermore, the <code>target</code> option inside <code>root_module</code> specify the target computer architecture (or the target operating system) of this binary file. For example, if you want this target object to run on a Windows machine that uses a <code>x86_64</code> architecture, you can set this <code>target</code> option to <code>x86_64-windows-gnu</code> for example. This will make the <code>zig</code> compiler to compile the project to run on a <code>x86_64</code> Windows machine. You can see the full list of architectures and OS’s that the <code>zig</code> compiler supports by running the <code>zig targets</code> command in the terminal.</p>
<p>Now, if you are building the project to run on the current machine that you are using to run this build script, you can set this <code>target</code> option to the <code>host</code> method of the <code>Build.graph</code> object, like we did in the example above. This <code>host</code> method identifies the current machine where you are currently running the <code>zig</code> compiler.</p>
<p>At last, the <code>.root_source_file</code> option inside <code>root_module</code> specifies the path to the root Zig module of your project. That is the Zig module that contains the entrypoint to your application (i.e., the <code>main()</code> function), or, the main API of your library. This also means that, all the Zig modules that compose your project are automatically discovered from the import statements you have inside this “root source file”. The <code>zig</code> compiler can detect when a Zig module depends on the other through the import statements, and, as a result, it can discover the entire map of Zig modules used in your project.</p>
<p>This is handy, and it’s different from what happens in other build systems. In CMake for example, you have to explicitly list the paths to all source files that you want to include in your build process. This is probably a symptom of the “lack of conditional compilation” in the C and C++ compilers. Since they lack this feature, you have to explicitly choose which source files should be sent to the C/C++ compiler, because not every C/C++ code is portable or supported in every operating system, and, therefore, would cause a compilation error in the C/C++ compiler.</p>
<p>Now, one important detail about the build process is that, you have to <strong>explicitly install the target objects that you create in your build script</strong>, by using the <code>installArtifact()</code> method of the <code>Build</code> struct.</p>
<p>Everytime you invoke the build process of your project, by calling the <code>build</code> command of the <code>zig</code> compiler, a new directory named <code>zig-out</code> is created in the root directory of your project. This new directory contains the outputs of the build process, that is, the binary files built from your source code.</p>
<p>What the <code>installArtifact()</code> method do is to install (or copy) the built target objects that you defined to this <code>zig-out</code> directory. This means that, if you do not install the target objects you define in your build script, these target objects are essentially discarded at the end of the build process.</p>
<p>For example, you might be building a project that uses a third party library that is built together with the project. So, when you build your project, you would need first, to build the third party library, and then, you link it with the source code of your project. So, in this case, we have two binary files that are generated in the build process (the executable file of your project, and the third party library). But only one is of interest, which is the executable file of our project. We can discard the binary file of the third party library, by simply not installing it into this <code>zig-out</code> directory.</p>
<p>This <code>installArtifact()</code> method is pretty straightforward. Just remember to apply it to every target object that you want to save into the <code>zig-out</code> directory, like in the example below:</p>
<div class="cell">
<div class="sourceCode cell-code" id="cb3"><pre class="sourceCode zig code-with-copy"><code class="sourceCode zig"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true" tabindex="-1"></a><span class="kw">const</span> exe = b.addExecutable(.<span class="op">{</span></span>
<span id="cb3-2"><a href="#cb3-2" aria-hidden="true" tabindex="-1"></a>    .name = <span class="st">"hello"</span>,</span>
<span id="cb3-3"><a href="#cb3-3" aria-hidden="true" tabindex="-1"></a>    .root_module = b.createModule(.<span class="op">{</span></span>
<span id="cb3-4"><a href="#cb3-4" aria-hidden="true" tabindex="-1"></a>        .root_source_file = b.path(<span class="st">"hello.zig"</span>),</span>
<span id="cb3-5"><a href="#cb3-5" aria-hidden="true" tabindex="-1"></a>        .target = b.graph.host</span>
<span id="cb3-6"><a href="#cb3-6" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span>)</span>
<span id="cb3-7"><a href="#cb3-7" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>);</span>
<span id="cb3-8"><a href="#cb3-8" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb3-9"><a href="#cb3-9" aria-hidden="true" tabindex="-1"></a>b.installArtifact(exe);</span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
</div>
</section>
<section id="setting-the-build-mode" class="level2" data-number="9.4">
<h2 data-number="9.4" class="anchored" data-anchor-id="setting-the-build-mode"><span class="header-section-number">9.4</span> Setting the build mode</h2>
<p>We have talked about the three essential options that are set when you create a new target object. But there is also a fourth option that you can use to set the build mode of this target object, which is the <code>optimize</code> option. This option is called this way, because the build modes in Zig are treated more of an “optimization vs safety” problem. So optimization plays an important role here. Don’t worry, I’m going back to this question very soon.</p>
<p>In Zig, we have four build modes (which are listed below). Each one of these build modes offer different advantages and characteristics. As we described in <a href="02-debugging.html#sec-compile-debug-mode" class="quarto-xref"><span>Section 5.2.1</span></a>, the <code>zig</code> compiler uses the <code>Debug</code> build mode by default, when you don’t explicitly choose a build mode.</p>
<ul>
<li><code>Debug</code>, mode that produces and includes debugging information in the output of the build process (i.e., the binary file defined by the target object);</li>
<li><code>ReleaseSmall</code>, mode that tries to produce a binary file that is small in size;</li>
<li><code>ReleaseFast</code>, mode that tries to optimize your code, in order to produce a binary file that is as fast as possible;</li>
<li><code>ReleaseSafe</code>, mode that tries to make your code as safe as possible, by including safeguards when possible.</li>
</ul>
<p>So, when you build your project, you can set the build mode of your target object to <code>ReleaseFast</code> for example, which will tell the <code>zig</code> compiler to apply important optimizations in your code. This creates a binary file that simply runs faster on most contexts, because it contains a more optimized version of your code. However, as a result, we often lose some safety features in our code. Because some safety checks are removed from the final binary file, which makes your code run faster, but in a less safe manner.</p>
<p>This choice depends on your current priorities. If you are building a cryptography or banking system, you might prefer to prioritize safety in your code, so, you would choose the <code>ReleaseSafe</code> build mode, which is a little slower to run, but much more secure, because it includes all possible runtime safety checks in the binary file built in the build process. In the other hand, if you are writing a game for example, you might prefer to prioritize performance over safety, by using the <code>ReleaseFast</code> build mode, so that your users can experience faster frame rates in your game.</p>
<p>In the example below, we are creating the same target object that we have used on previous examples. But this time, we are specifying the build mode of this target object to the <code>ReleaseSafe</code> mode.</p>
<div class="cell">
<div class="sourceCode cell-code" id="cb4"><pre class="sourceCode zig code-with-copy"><code class="sourceCode zig"><span id="cb4-1"><a href="#cb4-1" aria-hidden="true" tabindex="-1"></a><span class="kw">const</span> exe = b.addExecutable(.<span class="op">{</span></span>
<span id="cb4-2"><a href="#cb4-2" aria-hidden="true" tabindex="-1"></a>    .name = <span class="st">"hello"</span>,</span>
<span id="cb4-3"><a href="#cb4-3" aria-hidden="true" tabindex="-1"></a>    .root_module = b.createModule(.<span class="op">{</span></span>
<span id="cb4-4"><a href="#cb4-4" aria-hidden="true" tabindex="-1"></a>        .root_source_file = b.path(<span class="st">"hello.zig"</span>),</span>
<span id="cb4-5"><a href="#cb4-5" aria-hidden="true" tabindex="-1"></a>        .target = b.graph.host,</span>
<span id="cb4-6"><a href="#cb4-6" aria-hidden="true" tabindex="-1"></a>        .optimize = .ReleaseSafe</span>
<span id="cb4-7"><a href="#cb4-7" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span>)</span>
<span id="cb4-8"><a href="#cb4-8" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>);</span>
<span id="cb4-9"><a href="#cb4-9" aria-hidden="true" tabindex="-1"></a>b.installArtifact(exe);</span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
</div>
</section>
<section id="setting-the-version-of-your-build" class="level2" data-number="9.5">
<h2 data-number="9.5" class="anchored" data-anchor-id="setting-the-version-of-your-build"><span class="header-section-number">9.5</span> Setting the version of your build</h2>
<p>Everytime you build a target object in your build script, you can assign a version number to this specific build, following a semantic versioning framework. You can find more about semantic versioning by visiting the <a href="https://semver.org/">Semantic Versioning website</a><a href="#fn5" class="footnote-ref" id="fnref5" role="doc-noteref"><sup>5</sup></a>. Anyway, in Zig, you can specify the version of your build, by providing a <code>SemanticVersion</code> struct to the <code>version</code> option, like in the example below:</p>
<div class="cell">
<div class="sourceCode cell-code" id="cb5"><pre class="sourceCode zig code-with-copy"><code class="sourceCode zig"><span id="cb5-1"><a href="#cb5-1" aria-hidden="true" tabindex="-1"></a><span class="kw">const</span> exe = b.addExecutable(.<span class="op">{</span></span>
<span id="cb5-2"><a href="#cb5-2" aria-hidden="true" tabindex="-1"></a>    .name = <span class="st">"hello"</span>,</span>
<span id="cb5-3"><a href="#cb5-3" aria-hidden="true" tabindex="-1"></a>    .root_module = b.createModule(.<span class="op">{</span></span>
<span id="cb5-4"><a href="#cb5-4" aria-hidden="true" tabindex="-1"></a>        .root_source_file = b.path(<span class="st">"hello.zig"</span>),</span>
<span id="cb5-5"><a href="#cb5-5" aria-hidden="true" tabindex="-1"></a>        .target = b.graph.host</span>
<span id="cb5-6"><a href="#cb5-6" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span>),</span>
<span id="cb5-7"><a href="#cb5-7" aria-hidden="true" tabindex="-1"></a>    .version = .<span class="op">{</span></span>
<span id="cb5-8"><a href="#cb5-8" aria-hidden="true" tabindex="-1"></a>        .major = <span class="dv">2</span>, .minor = <span class="dv">9</span>, .patch = <span class="dv">7</span></span>
<span id="cb5-9"><a href="#cb5-9" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb5-10"><a href="#cb5-10" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>);</span>
<span id="cb5-11"><a href="#cb5-11" aria-hidden="true" tabindex="-1"></a>b.installArtifact(exe);</span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
</div>
</section>
<section id="sec-detect-os" class="level2" data-number="9.6">
<h2 data-number="9.6" class="anchored" data-anchor-id="sec-detect-os"><span class="header-section-number">9.6</span> Detecting the OS in your build script</h2>
<p>It’s very common in Build Systems to use different options, or, to include different modules, or, to link against different libraries depending on the Operational System (OS) that you are targeting in the build process.</p>
<p>In Zig, you can detect the target OS of the build process, by looking at the <code>os.tag</code> inside the <code>builtin</code> module from the Zig library. In the example below, we are using an if statement to run some arbitrary code when the target of the build process is a Windows system.</p>
<div class="cell">
<div class="sourceCode cell-code" id="cb6"><pre class="sourceCode zig code-with-copy"><code class="sourceCode zig"><span id="cb6-1"><a href="#cb6-1" aria-hidden="true" tabindex="-1"></a><span class="kw">const</span> builtin = <span class="bu">@import</span>(<span class="st">"builtin"</span>);</span>
<span id="cb6-2"><a href="#cb6-2" aria-hidden="true" tabindex="-1"></a><span class="kw">if</span> (builtin.target.os.tag == .windows) <span class="op">{</span></span>
<span id="cb6-3"><a href="#cb6-3" aria-hidden="true" tabindex="-1"></a>    <span class="co">// Code that runs only when the target of</span></span>
<span id="cb6-4"><a href="#cb6-4" aria-hidden="true" tabindex="-1"></a>    <span class="co">// the compilation process is Windows.</span></span>
<span id="cb6-5"><a href="#cb6-5" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
</div>
</section>
<section id="adding-a-run-step-to-your-build-process" class="level2" data-number="9.7">
<h2 data-number="9.7" class="anchored" data-anchor-id="adding-a-run-step-to-your-build-process"><span class="header-section-number">9.7</span> Adding a run step to your build process</h2>
<p>One thing that is neat in Rust is that you can compile and run your source code with one single command (<code>cargo run</code>) from the Rust compiler. We saw in <a href="01-zig-weird.html#sec-compile-run-code" class="quarto-xref"><span>Section 1.2.5</span></a> how can we perform a similar job in Zig, by building and running our Zig source code through the <code>run</code> command from the <code>zig</code> compiler.</p>
<p>But how can we, at the same time, build and run the binary file specified by a target object in our build script? The answer is by including a “run artifact” in our build script. A run artifact is created through the <code>addRunArtifact()</code> method from the <code>Build</code> struct. We simply provide as input to this function the target object that describes the binary file that we want to execute. As a result, this function creates a run artifact that is capable of executing this binary file.</p>
<p>In the example below, we are defining an executable binary file named <code>hello</code>, and we use this <code>addRunArtifact()</code> method to create a run artifact that will execute this <code>hello</code> executable file.</p>
<div class="cell">
<div class="sourceCode cell-code" id="cb7"><pre class="sourceCode zig code-with-copy"><code class="sourceCode zig"><span id="cb7-1"><a href="#cb7-1" aria-hidden="true" tabindex="-1"></a><span class="kw">const</span> exe = b.addExecutable(.<span class="op">{</span></span>
<span id="cb7-2"><a href="#cb7-2" aria-hidden="true" tabindex="-1"></a>    .name = <span class="st">"hello"</span>,</span>
<span id="cb7-3"><a href="#cb7-3" aria-hidden="true" tabindex="-1"></a>    .root_module = b.createModule(.<span class="op">{</span></span>
<span id="cb7-4"><a href="#cb7-4" aria-hidden="true" tabindex="-1"></a>        .root_source_file = b.path(<span class="st">"src/hello.zig"</span>),</span>
<span id="cb7-5"><a href="#cb7-5" aria-hidden="true" tabindex="-1"></a>        .target = b.graph.host</span>
<span id="cb7-6"><a href="#cb7-6" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span>)</span>
<span id="cb7-7"><a href="#cb7-7" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>);</span>
<span id="cb7-8"><a href="#cb7-8" aria-hidden="true" tabindex="-1"></a>b.installArtifact(exe);</span>
<span id="cb7-9"><a href="#cb7-9" aria-hidden="true" tabindex="-1"></a><span class="kw">const</span> run_arti = b.addRunArtifact(exe);</span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
</div>
<p>Now that we have created this run artifact, we need to include it in the build process. We do that by declaring a new step in our build script to call this artifact, through the <code>step()</code> method of the <code>Build</code> struct.</p>
<p>We can give any name we want to this step, but, for our context here, I’m going to name this step as “run”. Also, I give it a brief description to this step (“Run the project”).</p>
<div class="cell">
<div class="sourceCode cell-code" id="cb8"><pre class="sourceCode zig code-with-copy"><code class="sourceCode zig"><span id="cb8-1"><a href="#cb8-1" aria-hidden="true" tabindex="-1"></a><span class="kw">const</span> run_step = b.step(</span>
<span id="cb8-2"><a href="#cb8-2" aria-hidden="true" tabindex="-1"></a>    <span class="st">"run"</span>, <span class="st">"Run the project"</span></span>
<span id="cb8-3"><a href="#cb8-3" aria-hidden="true" tabindex="-1"></a>);</span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
</div>
<p>Now that we have declared this “run step” we need to tell Zig that this “run step” depends on the run artifact. In other words, a run artifact always depends on a “step” to effectively be executed. By creating this dependency we finally stablish the necessary commands to build and run the executable file from the build script.</p>
<p>We can establish a dependency between the run step and the run artifact by using the <code>dependOn()</code> method from the run step. So, we first create the run step, and then, we link it with the run artifact, by using this <code>dependOn()</code> method from the run step.</p>
<div class="cell">
<div class="sourceCode cell-code" id="cb9"><pre class="sourceCode zig code-with-copy"><code class="sourceCode zig"><span id="cb9-1"><a href="#cb9-1" aria-hidden="true" tabindex="-1"></a>run_step.dependOn(&amp;run_arti.step);</span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
</div>
<p>The entire source code of this specific build script that we wrote, piece by piece, in this section, is available in the <code>build_and_run.zig</code> module. You can see this module by <a href="https://github.com/pedropark99/zig-book/blob/main/ZigExamples/build_system/build_and_run.zig">visiting the official repository of this book</a> <a href="#fn6" class="footnote-ref" id="fnref6" role="doc-noteref"><sup>6</sup></a>.</p>
<p>When you declare a new step in your build script, this step becomes available through the <code>build</code> command in the <code>zig</code> compiler. You can actually see this step by running <code>zig build --help</code> in the terminal, like in the example below, where we can see that this new “run” step that we declared in the build script appeared in the output.</p>
<div class="sourceCode" id="cb10"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb10-1"><a href="#cb10-1" aria-hidden="true" tabindex="-1"></a><span class="ex">zig</span> build <span class="at">--help</span></span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
<pre><code>Steps:
  ...
  run   Run the project
  ...</code></pre>
<p>Now, everything that we need to is to call this “run” step that we created in our build script. We call it by using the name that we gave to this step after the <code>build</code> command from the <code>zig</code> compiler. This will cause the compiler to build our executable file and execute it at the same time.</p>
<div class="sourceCode" id="cb12"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb12-1"><a href="#cb12-1" aria-hidden="true" tabindex="-1"></a><span class="ex">zig</span> build run</span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
</section>
<section id="build-unit-tests-in-your-project" class="level2" data-number="9.8">
<h2 data-number="9.8" class="anchored" data-anchor-id="build-unit-tests-in-your-project"><span class="header-section-number">9.8</span> Build unit tests in your project</h2>
<p>We have talked at length about writing unit tests in Zig in <a href="03-unittests.html" class="quarto-xref"><span>Chapter 8</span></a>, and we also have talked about how to execute these unit tests through the <code>test</code> command of the <code>zig</code> compiler. However, as we did with the <code>run</code> command on the previous section, we also might want to include some commands in our build script to also build and execute the unit tests in our project.</p>
<p>So, once again, we are going to discuss how a specific built-in command from the <code>zig</code> compiler, (in this case, the <code>test</code> command) can be used in a build script in Zig. Here is where a “test target object” comes into play. As was described in <a href="#sec-targets" class="quarto-xref"><span>Section 9.3</span></a>, we can create a test target object by using the <code>addTest()</code> method of the <code>Build</code> struct. The first thing that we need to do is to declare a test target object in our build script.</p>
<div class="cell">
<div class="sourceCode cell-code" id="cb13"><pre class="sourceCode zig code-with-copy"><code class="sourceCode zig"><span id="cb13-1"><a href="#cb13-1" aria-hidden="true" tabindex="-1"></a><span class="kw">const</span> test_exe = b.addTest(.<span class="op">{</span></span>
<span id="cb13-2"><a href="#cb13-2" aria-hidden="true" tabindex="-1"></a>    .name = <span class="st">"unit_tests"</span>,</span>
<span id="cb13-3"><a href="#cb13-3" aria-hidden="true" tabindex="-1"></a>    .root_module = b.createModule(.<span class="op">{</span></span>
<span id="cb13-4"><a href="#cb13-4" aria-hidden="true" tabindex="-1"></a>        .root_source_file = b.path(<span class="st">"src/main.zig"</span>),</span>
<span id="cb13-5"><a href="#cb13-5" aria-hidden="true" tabindex="-1"></a>        .target = b.graph.host</span>
<span id="cb13-6"><a href="#cb13-6" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span>)</span>
<span id="cb13-7"><a href="#cb13-7" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>);</span>
<span id="cb13-8"><a href="#cb13-8" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb13-9"><a href="#cb13-9" aria-hidden="true" tabindex="-1"></a>b.installArtifact(test_exe);</span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
</div>
<p>A test target object essentially selects all <code>test</code> blocks in all Zig modules across your project, and builds only the source code present inside these <code>test</code> blocks in your project. As a result, this target object creates an executable file that contains only the source code present in all of these <code>test</code> blocks (i.e., the unit tests) in your project.</p>
<p>Perfect! Now that we have declared this test target object, an executable file named <code>unit_tests</code> is built by the <code>zig</code> compiler when we trigger the build script with the <code>build</code> command. After the build process is finished, we can simply execute this <code>unit_tests</code> executable in the terminal.</p>
<p>However, if you remember the previous section, we already learned how can we create a run step in our build script, to execute an executable file built by the build script.</p>
<p>So, we could simply add a run step in our build script to run these unit tests from a single command in the <code>zig</code> compiler, to make our lifes easier. In the example below, we demonstrate the commands to register a new build step called “tests” in our build script to run these unit tests.</p>
<div class="cell">
<div class="sourceCode cell-code" id="cb14"><pre class="sourceCode zig code-with-copy"><code class="sourceCode zig"><span id="cb14-1"><a href="#cb14-1" aria-hidden="true" tabindex="-1"></a><span class="kw">const</span> run_arti = b.addRunArtifact(test_exe);</span>
<span id="cb14-2"><a href="#cb14-2" aria-hidden="true" tabindex="-1"></a><span class="kw">const</span> run_step = b.step(<span class="st">"tests"</span>, <span class="st">"Run unit tests"</span>);</span>
<span id="cb14-3"><a href="#cb14-3" aria-hidden="true" tabindex="-1"></a>run_step.dependOn(&amp;run_arti.step);</span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
</div>
<p>Now that we registered this new build step, we can trigger it by calling the command below in the terminal. You can also checkout the complete source code for this specific build script at the <code>build_tests.zig</code> module at the <a href="https://github.com/pedropark99/zig-book/blob/main/ZigExamples/build_system/build_tests.zig">official repository of this book</a> <a href="#fn7" class="footnote-ref" id="fnref7" role="doc-noteref"><sup>7</sup></a>.</p>
<div class="sourceCode" id="cb15"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb15-1"><a href="#cb15-1" aria-hidden="true" tabindex="-1"></a><span class="ex">zig</span> build tests</span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
</section>
<section id="tailoring-your-build-process-with-user-provided-options" class="level2" data-number="9.9">
<h2 data-number="9.9" class="anchored" data-anchor-id="tailoring-your-build-process-with-user-provided-options"><span class="header-section-number">9.9</span> Tailoring your build process with user-provided options</h2>
<p>Sometimes, you want to make a build script that is customizable by the user of your project. You can do that by creating user-provided options in your build script. We create an user-provided option by using the <code>option()</code> method from the <code>Build</code> struct.</p>
<p>With this method, we create a “build option” which can be passed to the <code>build.zig</code> script at the command line. The user have the power of setting this option at the <code>build</code> command from the <code>zig</code> compiler. In other words, each build option that we create becomes a new command line argument that is accessible through the <code>build</code> command of the compiler.</p>
<p>These “user-provided options” are set by using the prefix <code>-D</code> in the command line. For example, if we declare an option named <code>use_zlib</code>, that receives a boolean value which indicates if we should link our source code to <code>zlib</code> or not, we can set the value of this option in the command line with <code>-Duse_zlib</code>. The code example below demonstrates this idea:</p>
<div class="cell">
<div class="sourceCode cell-code" id="cb16"><pre class="sourceCode zig code-with-copy"><code class="sourceCode zig"><span id="cb16-1"><a href="#cb16-1" aria-hidden="true" tabindex="-1"></a><span class="kw">const</span> std = <span class="bu">@import</span>(<span class="st">"std"</span>);</span>
<span id="cb16-2"><a href="#cb16-2" aria-hidden="true" tabindex="-1"></a><span class="kw">pub</span> <span class="kw">fn</span> build(b: *std.Build) <span class="dt">void</span> <span class="op">{</span></span>
<span id="cb16-3"><a href="#cb16-3" aria-hidden="true" tabindex="-1"></a>    <span class="kw">const</span> use_zlib = b.option(</span>
<span id="cb16-4"><a href="#cb16-4" aria-hidden="true" tabindex="-1"></a>        <span class="dt">bool</span>,</span>
<span id="cb16-5"><a href="#cb16-5" aria-hidden="true" tabindex="-1"></a>        <span class="st">"use_zlib"</span>,</span>
<span id="cb16-6"><a href="#cb16-6" aria-hidden="true" tabindex="-1"></a>        <span class="st">"Should link to zlib?"</span></span>
<span id="cb16-7"><a href="#cb16-7" aria-hidden="true" tabindex="-1"></a>    ) <span class="kw">orelse</span> <span class="cn">false</span>;</span>
<span id="cb16-8"><a href="#cb16-8" aria-hidden="true" tabindex="-1"></a>    <span class="kw">const</span> exe = b.addExecutable(.<span class="op">{</span></span>
<span id="cb16-9"><a href="#cb16-9" aria-hidden="true" tabindex="-1"></a>        .name = <span class="st">"hello"</span>,</span>
<span id="cb16-10"><a href="#cb16-10" aria-hidden="true" tabindex="-1"></a>        .root_module = b.createModule(.<span class="op">{</span></span>
<span id="cb16-11"><a href="#cb16-11" aria-hidden="true" tabindex="-1"></a>            .root_source_file = b.path(<span class="st">"example.zig"</span>),</span>
<span id="cb16-12"><a href="#cb16-12" aria-hidden="true" tabindex="-1"></a>            .target = b.graph.host</span>
<span id="cb16-13"><a href="#cb16-13" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span>)</span>
<span id="cb16-14"><a href="#cb16-14" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span>);</span>
<span id="cb16-15"><a href="#cb16-15" aria-hidden="true" tabindex="-1"></a>    <span class="kw">if</span> (use_zlib) <span class="op">{</span></span>
<span id="cb16-16"><a href="#cb16-16" aria-hidden="true" tabindex="-1"></a>        exe.root_module.linkSystemLibrary(<span class="st">"zlib"</span>, .<span class="op">{}</span>);</span>
<span id="cb16-17"><a href="#cb16-17" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb16-18"><a href="#cb16-18" aria-hidden="true" tabindex="-1"></a>    b.installArtifact(exe);</span>
<span id="cb16-19"><a href="#cb16-19" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
</div>
<div class="sourceCode" id="cb17"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb17-1"><a href="#cb17-1" aria-hidden="true" tabindex="-1"></a><span class="ex">zig</span> build <span class="at">-Duse_zlib</span><span class="op">=</span>false</span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
</section>
<section id="linking-to-external-libraries" class="level2" data-number="9.10">
<h2 data-number="9.10" class="anchored" data-anchor-id="linking-to-external-libraries"><span class="header-section-number">9.10</span> Linking to external libraries</h2>
<p>One essential part of every build process is the linking stage. This stage is responsible for combining the multiple object files that represent your code, into a single executable file. It also links this executable file to external libraries, if you use any in your code.</p>
<p>In Zig, we have two notions of a “library”, which are: 1) a system’s library; 2) a local library. A system’s library is just a library that is already installed in your system. While a local library is a library that belongs to the current project; a library that is present in your project directory, and that you are building together with your project source code.</p>
<p>The basic difference between the two, is that a system’s library is already built and installed in your system, supposedly, and all you need to do is to link your source code to this library to start using it. We do that by using the <code>linkSystemLibrary()</code> method from a <code>Compile.root_module</code> object. This method accepts the name of the library in a string as input. Remember from <a href="#sec-targets" class="quarto-xref"><span>Section 9.3</span></a> that a <code>Compile</code> object is a target object that you declare in your build script.</p>
<p>When you link a particular target object with a system’s library, the <code>zig</code> compiler will use <code>pkg-config</code> to find where are the binary files and also the header files of this library in your system. When it finds these files, the linker present in the <code>zig</code> compiler will link your object files with the files of this library to produce a single binary file for you.</p>
<p>In the example below, we are creating an executable file named <code>image_filter</code>, and, we are linking this executable file to the C Standard Library by setting the <code>link_libc</code> option to <code>true</code>. But we also link this executable file to the C library <code>libpng</code> that is currently installed in my system.</p>
<div class="cell">
<div class="sourceCode cell-code" id="cb18"><pre class="sourceCode zig code-with-copy"><code class="sourceCode zig"><span id="cb18-1"><a href="#cb18-1" aria-hidden="true" tabindex="-1"></a><span class="kw">const</span> std = <span class="bu">@import</span>(<span class="st">"std"</span>);</span>
<span id="cb18-2"><a href="#cb18-2" aria-hidden="true" tabindex="-1"></a><span class="kw">pub</span> <span class="kw">fn</span> build(b: *std.Build) <span class="dt">void</span> <span class="op">{</span></span>
<span id="cb18-3"><a href="#cb18-3" aria-hidden="true" tabindex="-1"></a>    <span class="kw">const</span> exe = b.addExecutable(.<span class="op">{</span></span>
<span id="cb18-4"><a href="#cb18-4" aria-hidden="true" tabindex="-1"></a>        .name = <span class="st">"image_filter"</span>,</span>
<span id="cb18-5"><a href="#cb18-5" aria-hidden="true" tabindex="-1"></a>        .root_module = b.createModule(.<span class="op">{</span></span>
<span id="cb18-6"><a href="#cb18-6" aria-hidden="true" tabindex="-1"></a>            .root_source_file = b.path(<span class="st">"src/main.zig"</span>),</span>
<span id="cb18-7"><a href="#cb18-7" aria-hidden="true" tabindex="-1"></a>            .target = b.graph.host</span>
<span id="cb18-8"><a href="#cb18-8" aria-hidden="true" tabindex="-1"></a>            .link_libc = <span class="cn">true</span>,</span>
<span id="cb18-9"><a href="#cb18-9" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span>)</span>
<span id="cb18-10"><a href="#cb18-10" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span>);</span>
<span id="cb18-11"><a href="#cb18-11" aria-hidden="true" tabindex="-1"></a>    exe.root_module.linkSystemLibrary(<span class="st">"png"</span>, .<span class="op">{}</span>);</span>
<span id="cb18-12"><a href="#cb18-12" aria-hidden="true" tabindex="-1"></a>    b.installArtifact(exe);</span>
<span id="cb18-13"><a href="#cb18-13" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
</div>
<p>If you are linking with a C library in your project, is generally a good idea to also link your code with the C Standard Library. Because is very likely that this C library uses some functionality of the C Standard Library at some point. The same goes to C++ libraries. So, if you are linking with C++ libraries, is a good idea to link your project with the C++ Standard Library by setting the <code>link_libcpp</code> option to <code>true</code>.</p>
<p>On the order side, when you want to link with a local library, you should use the <code>linkLibrary()</code> method of a <code>Compile.root_module</code> object. This method expects to receive another <code>Compile</code> object as input. That is, another target object defined in your build script, using either the <code>addStaticLibrary()</code> or <code>addSharedLibrary()</code> methods which defines a library to be built.</p>
<p>As we discussed earlier, a local library is a library that is local to your project, and that is being built together with your project. So, you need to create a target object in your build script to build this local library. Then, you link the target objects of interest in your project, with this target object that identifies this local library.</p>
<p>Take a look at this example extracted from the build script of the <a href="https://github.com/mitchellh/libxev/tree/main"><code>libxev</code> library</a><a href="#fn8" class="footnote-ref" id="fnref8" role="doc-noteref"><sup>8</sup></a>. You can see in this snippet that we are declaring a shared library file, from the <code>c_api.zig</code> module. Then, later in the build script, we declare an executable file named <code>"dynamic-binding-test"</code>, which links to this shared library that we defined earlier in the script.</p>
<div class="cell">
<div class="sourceCode cell-code" id="cb19"><pre class="sourceCode zig code-with-copy"><code class="sourceCode zig"><span id="cb19-1"><a href="#cb19-1" aria-hidden="true" tabindex="-1"></a><span class="kw">const</span> dynamic_lib = b.addSharedLibrary(.<span class="op">{</span></span>
<span id="cb19-2"><a href="#cb19-2" aria-hidden="true" tabindex="-1"></a>    .name = dynamic_lib_name,</span>
<span id="cb19-3"><a href="#cb19-3" aria-hidden="true" tabindex="-1"></a>    .root_module = b.createModule(.<span class="op">{</span></span>
<span id="cb19-4"><a href="#cb19-4" aria-hidden="true" tabindex="-1"></a>        .root_source_file = b.path(<span class="st">"src/c_api.zig"</span>),</span>
<span id="cb19-5"><a href="#cb19-5" aria-hidden="true" tabindex="-1"></a>        .target = b.graph.host</span>
<span id="cb19-6"><a href="#cb19-6" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span>)</span>
<span id="cb19-7"><a href="#cb19-7" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>);</span>
<span id="cb19-8"><a href="#cb19-8" aria-hidden="true" tabindex="-1"></a>b.installArtifact(dynamic_lib);</span>
<span id="cb19-9"><a href="#cb19-9" aria-hidden="true" tabindex="-1"></a><span class="co">// ... more lines in the script</span></span>
<span id="cb19-10"><a href="#cb19-10" aria-hidden="true" tabindex="-1"></a><span class="kw">const</span> dynamic_binding_test = b.addExecutable(.<span class="op">{</span></span>
<span id="cb19-11"><a href="#cb19-11" aria-hidden="true" tabindex="-1"></a>    .name = <span class="st">"dynamic-binding-test"</span>,</span>
<span id="cb19-12"><a href="#cb19-12" aria-hidden="true" tabindex="-1"></a>    .root_module = b.createModule(.<span class="op">{</span></span>
<span id="cb19-13"><a href="#cb19-13" aria-hidden="true" tabindex="-1"></a>        .root_source_file = b.path(<span class="st">"src/test.zig"</span>),</span>
<span id="cb19-14"><a href="#cb19-14" aria-hidden="true" tabindex="-1"></a>        .target = b.graph.host</span>
<span id="cb19-15"><a href="#cb19-15" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span>)</span>
<span id="cb19-16"><a href="#cb19-16" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>);</span>
<span id="cb19-17"><a href="#cb19-17" aria-hidden="true" tabindex="-1"></a>dynamic_binding_test.root_module.linkLibrary(</span>
<span id="cb19-18"><a href="#cb19-18" aria-hidden="true" tabindex="-1"></a>    dynamic_lib</span>
<span id="cb19-19"><a href="#cb19-19" aria-hidden="true" tabindex="-1"></a>);</span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
</div>
</section>
<section id="sec-building-c-code" class="level2" data-number="9.11">
<h2 data-number="9.11" class="anchored" data-anchor-id="sec-building-c-code"><span class="header-section-number">9.11</span> Building C code</h2>
<p>The <code>zig</code> compiler comes with a C compiler embedded in it. In other words, you can use the <code>zig</code> compiler to build C projects. This C compiler is available through the <code>cc</code> command of the <code>zig</code> compiler.</p>
<p>As an example, let’s use the famous <a href="https://freetype.org/">FreeType library</a><a href="#fn9" class="footnote-ref" id="fnref9" role="doc-noteref"><sup>9</sup></a>. FreeType is one of the most widely used pieces of software in the world. It’s a C library designed to produce high-quality fonts. But it’s also heavily used in the industry to natively render text and fonts in the screen of your computer.</p>
<p>In this section, we are going to write a build script, piece by piece, that is capable of building the FreeType project from source. You can find the source code of this build script on the <a href="https://github.com/pedropark99/freetype-zig/tree/main"><code>freetype-zig</code> repository</a><a href="#fn10" class="footnote-ref" id="fnref10" role="doc-noteref"><sup>10</sup></a> available at GitHub.</p>
<p>After you download the source code of FreeType from the official website<a href="#fn11" class="footnote-ref" id="fnref11" role="doc-noteref"><sup>11</sup></a>, you can start writing the <code>build.zig</code> module. We begin by defining the target object that defines the binary file that we want to compile.</p>
<p>As an example, I will build the project as a static library file using the <code>addStaticLibrary()</code> method to create the target object. Also, since FreeType is a C library, I will also link the library against <code>libc</code> through the <code>link_libc</code> option, to guarantee that any use of the C Standard Library is covered in the compilation process.</p>
<div class="cell">
<div class="sourceCode cell-code" id="cb20"><pre class="sourceCode zig code-with-copy"><code class="sourceCode zig"><span id="cb20-1"><a href="#cb20-1" aria-hidden="true" tabindex="-1"></a><span class="kw">const</span> lib = b.addStaticLibrary(.<span class="op">{</span></span>
<span id="cb20-2"><a href="#cb20-2" aria-hidden="true" tabindex="-1"></a>    .name = <span class="st">"freetype"</span>,</span>
<span id="cb20-3"><a href="#cb20-3" aria-hidden="true" tabindex="-1"></a>    .root_module = b.createModule(.<span class="op">{</span></span>
<span id="cb20-4"><a href="#cb20-4" aria-hidden="true" tabindex="-1"></a>        .target = b.graph.host,</span>
<span id="cb20-5"><a href="#cb20-5" aria-hidden="true" tabindex="-1"></a>        .link_libc = <span class="cn">true</span></span>
<span id="cb20-6"><a href="#cb20-6" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span>)</span>
<span id="cb20-7"><a href="#cb20-7" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>);</span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
</div>
<section id="creating-c-compiler-flags" class="level3" data-number="9.11.1">
<h3 data-number="9.11.1" class="anchored" data-anchor-id="creating-c-compiler-flags"><span class="header-section-number">9.11.1</span> Creating C compiler flags</h3>
<p>Compiler flags are also known as “compiler options” by many programmers, or also, as “command options” in the GCC official documentation. It’s fair to also call them as the “command-line arguments” of the C compiler. In general, we use compiler flags to turn on (or turn off) some features from the compiler, or to tweak the compilation process to fit the needs of our project.</p>
<p>In build scripts written in Zig, we normally list the C compiler flags to be used in the compilation process in a simple array, like in the example below.</p>
<div class="cell">
<div class="sourceCode cell-code" id="cb21"><pre class="sourceCode zig code-with-copy"><code class="sourceCode zig"><span id="cb21-1"><a href="#cb21-1" aria-hidden="true" tabindex="-1"></a><span class="kw">const</span> c_flags = [_][]<span class="kw">const</span> <span class="dt">u8</span><span class="op">{</span></span>
<span id="cb21-2"><a href="#cb21-2" aria-hidden="true" tabindex="-1"></a>    <span class="st">"-Wall"</span>,</span>
<span id="cb21-3"><a href="#cb21-3" aria-hidden="true" tabindex="-1"></a>    <span class="st">"-Wextra"</span>,</span>
<span id="cb21-4"><a href="#cb21-4" aria-hidden="true" tabindex="-1"></a>    <span class="st">"-Werror"</span>,</span>
<span id="cb21-5"><a href="#cb21-5" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
</div>
<p>In theory, there is nothing stopping you from using this array to add “include paths” (with the <code>-I</code> flag) or “library paths” (with the <code>-L</code> flag) to the compilation process. But there are formal ways in Zig to add these types of paths in the compilation process. Both are discussed in <a href="#sec-include-paths" class="quarto-xref"><span>Section 9.11.5</span></a> and <a href="#sec-library-paths" class="quarto-xref"><span>Section 9.11.4</span></a>.</p>
<p>Anyway, in Zig, we add C flags to the build process together with the C files that we want to compile, by using the <code>addCSourceFile()</code> and <code>addCSourceFiles()</code> methods. In the example above, we have just declared the C flags that we want to use. But we haven’t added them to the build process yet. To do that, we also need to list the C files to be compiled.</p>
</section>
<section id="listing-your-c-files" class="level3" data-number="9.11.2">
<h3 data-number="9.11.2" class="anchored" data-anchor-id="listing-your-c-files"><span class="header-section-number">9.11.2</span> Listing your C files</h3>
<p>The C files that contains “cross-platform” source code are listed in the <code>c_source_files</code> object below. These are the C files that are included by default in every platform supported by the FreeType library. Now, since the amount of C files in the FreeType library is big, I have omitted the rest of the files in the code example below, for brevity purposes.</p>
<div class="cell">
<div class="sourceCode cell-code" id="cb22"><pre class="sourceCode zig code-with-copy"><code class="sourceCode zig"><span id="cb22-1"><a href="#cb22-1" aria-hidden="true" tabindex="-1"></a><span class="kw">const</span> c_source_files = [_][]<span class="kw">const</span> <span class="dt">u8</span><span class="op">{</span></span>
<span id="cb22-2"><a href="#cb22-2" aria-hidden="true" tabindex="-1"></a>    <span class="st">"src/autofit/autofit.c"</span>,</span>
<span id="cb22-3"><a href="#cb22-3" aria-hidden="true" tabindex="-1"></a>    <span class="st">"src/base/ftbase.c"</span>,</span>
<span id="cb22-4"><a href="#cb22-4" aria-hidden="true" tabindex="-1"></a>    <span class="co">// ... and many other C files.</span></span>
<span id="cb22-5"><a href="#cb22-5" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
</div>
<p>Now, in addition to “cross-platform” source code, we also have some C files in the FreeType project that are platform-specific, meaning that, they contain source code that can only be compiled in specific platforms, and, as a result, they are only included in the build process on these specific target platforms. The objects that list these C files are exposed in the code example below.</p>
<div class="cell">
<div class="sourceCode cell-code" id="cb23"><pre class="sourceCode zig code-with-copy"><code class="sourceCode zig"><span id="cb23-1"><a href="#cb23-1" aria-hidden="true" tabindex="-1"></a><span class="kw">const</span> windows_c_source_files = [_][]<span class="kw">const</span> <span class="dt">u8</span><span class="op">{</span></span>
<span id="cb23-2"><a href="#cb23-2" aria-hidden="true" tabindex="-1"></a>    <span class="st">"builds/windows/ftdebug.c"</span>,</span>
<span id="cb23-3"><a href="#cb23-3" aria-hidden="true" tabindex="-1"></a>    <span class="st">"builds/windows/ftsystem.c"</span></span>
<span id="cb23-4"><a href="#cb23-4" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span>
<span id="cb23-5"><a href="#cb23-5" aria-hidden="true" tabindex="-1"></a><span class="kw">const</span> linux_c_source_files = [_][]<span class="kw">const</span> <span class="dt">u8</span><span class="op">{</span></span>
<span id="cb23-6"><a href="#cb23-6" aria-hidden="true" tabindex="-1"></a>    <span class="st">"src/base/ftsystem.c"</span>,</span>
<span id="cb23-7"><a href="#cb23-7" aria-hidden="true" tabindex="-1"></a>    <span class="st">"src/base/ftdebug.c"</span></span>
<span id="cb23-8"><a href="#cb23-8" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
</div>
<p>Now that we declared both the files that we want to include and the C compiler flags to be used, we can add them to the target object that describes the FreeType library, by using the <code>addCSourceFile()</code> and <code>addCSourceFiles()</code> methods.</p>
<p>Both of these functions are methods from a <code>Compile.root_module</code> object. The <code>addCSourceFile()</code> method is capable of adding a single C file to the target object, while the <code>addCSourceFiles()</code> method is used to add multiple C files in a single command. You might prefer to use <code>addCSourceFile()</code> when you need to use different compiler flags on specific C files in your project. But, if you can use the same compiler flags across all C files, then, you will probably find <code>addCSourceFiles()</code> a better choice.</p>
<p>Notice that we are using the <code>addCSourceFiles()</code> method in the example below, to add both the C files and the C compiler flags. Also notice that we are using the <code>os.tag</code> that we learned about in <a href="#sec-detect-os" class="quarto-xref"><span>Section 9.6</span></a>, to add the platform-specific C files.</p>
<div class="cell">
<div class="sourceCode cell-code" id="cb24"><pre class="sourceCode zig code-with-copy"><code class="sourceCode zig"><span id="cb24-1"><a href="#cb24-1" aria-hidden="true" tabindex="-1"></a><span class="kw">const</span> builtin = <span class="bu">@import</span>(<span class="st">"builtin"</span>);</span>
<span id="cb24-2"><a href="#cb24-2" aria-hidden="true" tabindex="-1"></a>lib.root_module.addCSourceFiles(<span class="op">{</span></span>
<span id="cb24-3"><a href="#cb24-3" aria-hidden="true" tabindex="-1"></a>    .files=&amp;c_source_files,</span>
<span id="cb24-4"><a href="#cb24-4" aria-hidden="true" tabindex="-1"></a>    .flags=&amp;c_flags</span>
<span id="cb24-5"><a href="#cb24-5" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>);</span>
<span id="cb24-6"><a href="#cb24-6" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb24-7"><a href="#cb24-7" aria-hidden="true" tabindex="-1"></a><span class="kw">switch</span> (builtin.target.os.tag) <span class="op">{</span></span>
<span id="cb24-8"><a href="#cb24-8" aria-hidden="true" tabindex="-1"></a>    .windows =&gt; <span class="op">{</span></span>
<span id="cb24-9"><a href="#cb24-9" aria-hidden="true" tabindex="-1"></a>        lib.root_module.addCSourceFiles(<span class="op">{</span></span>
<span id="cb24-10"><a href="#cb24-10" aria-hidden="true" tabindex="-1"></a>            .files=&amp;windows_c_source_files,</span>
<span id="cb24-11"><a href="#cb24-11" aria-hidden="true" tabindex="-1"></a>            .flags=&amp;c_flags</span>
<span id="cb24-12"><a href="#cb24-12" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span>);</span>
<span id="cb24-13"><a href="#cb24-13" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span>,</span>
<span id="cb24-14"><a href="#cb24-14" aria-hidden="true" tabindex="-1"></a>    .linux =&gt; <span class="op">{</span></span>
<span id="cb24-15"><a href="#cb24-15" aria-hidden="true" tabindex="-1"></a>        lib.root_module.addCSourceFiles(<span class="op">{</span></span>
<span id="cb24-16"><a href="#cb24-16" aria-hidden="true" tabindex="-1"></a>            .files=&amp;linux_c_source_files,</span>
<span id="cb24-17"><a href="#cb24-17" aria-hidden="true" tabindex="-1"></a>            .flags=&amp;c_flags</span>
<span id="cb24-18"><a href="#cb24-18" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span>);</span>
<span id="cb24-19"><a href="#cb24-19" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span>,</span>
<span id="cb24-20"><a href="#cb24-20" aria-hidden="true" tabindex="-1"></a>    <span class="kw">else</span> =&gt; <span class="op">{}</span>,</span>
<span id="cb24-21"><a href="#cb24-21" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
</div>
</section>
<section id="defining-c-macros" class="level3" data-number="9.11.3">
<h3 data-number="9.11.3" class="anchored" data-anchor-id="defining-c-macros"><span class="header-section-number">9.11.3</span> Defining C Macros</h3>
<p>C Macros are an essential part of the C programming language, and they are commonly defined through the <code>-D</code> flag from a C compiler. In Zig, you can define a C Macro to be used in your build process by using the <code>addCMacro()</code> method from the <code>root_module</code> attribute of the target object that defines the binary file that you are building.</p>
<p>In the example below, we are using the <code>lib</code> object that we have defined in the previous sections to define some C Macros used by the FreeType project in the compilation process. These C Macros specify if FreeType should (or should not) include functionalities from different external libraries.</p>
<div class="cell">
<div class="sourceCode cell-code" id="cb25"><pre class="sourceCode zig code-with-copy"><code class="sourceCode zig"><span id="cb25-1"><a href="#cb25-1" aria-hidden="true" tabindex="-1"></a>lib.root_module.addCMacro(<span class="st">"FT_DISABLE_ZLIB"</span>, <span class="st">"TRUE"</span>);</span>
<span id="cb25-2"><a href="#cb25-2" aria-hidden="true" tabindex="-1"></a>lib.root_module.addCMacro(<span class="st">"FT_DISABLE_PNG"</span>, <span class="st">"TRUE"</span>);</span>
<span id="cb25-3"><a href="#cb25-3" aria-hidden="true" tabindex="-1"></a>lib.root_module.addCMacro(<span class="st">"FT_DISABLE_HARFBUZZ"</span>, <span class="st">"TRUE"</span>);</span>
<span id="cb25-4"><a href="#cb25-4" aria-hidden="true" tabindex="-1"></a>lib.root_module.addCMacro(<span class="st">"FT_DISABLE_BZIP2"</span>, <span class="st">"TRUE"</span>);</span>
<span id="cb25-5"><a href="#cb25-5" aria-hidden="true" tabindex="-1"></a>lib.root_module.addCMacro(<span class="st">"FT_DISABLE_BROTLI"</span>, <span class="st">"TRUE"</span>);</span>
<span id="cb25-6"><a href="#cb25-6" aria-hidden="true" tabindex="-1"></a>lib.root_module.addCMacro(<span class="st">"FT2_BUILD_LIBRARY"</span>, <span class="st">"TRUE"</span>);</span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
</div>
</section>
<section id="sec-library-paths" class="level3" data-number="9.11.4">
<h3 data-number="9.11.4" class="anchored" data-anchor-id="sec-library-paths"><span class="header-section-number">9.11.4</span> Adding library paths</h3>
<p>Library paths are paths in your computer where the C compiler will look (or search) for library files to link against your source code. In other words, when you use a library in your C source code, and you ask the C compiler to link your source code against this library, the C compiler will search for the binary files of this library across the paths listed in this “library paths” set.</p>
<p>These paths are platform specific, and, by default, the C compiler starts by looking at a pre-defined set of places in your computer. But you can add more paths (or more places) to this list. For example, you may have a library installed in a non-conventional place of your computer, and you can make the C compiler “see” this “non-conventional place” by adding this path to this list of pre-defined paths.</p>
<p>In Zig, you can add more paths to this set by using the <code>addLibraryPath()</code> method from the <code>root_module</code> attribute of your target object. First, you defined a <code>LazyPath</code> object, containing the path you want to add, then, you provide this object as input to the <code>addLibraryPath()</code> method, like in the example below:</p>
<div class="cell">
<div class="sourceCode cell-code" id="cb26"><pre class="sourceCode zig code-with-copy"><code class="sourceCode zig"><span id="cb26-1"><a href="#cb26-1" aria-hidden="true" tabindex="-1"></a><span class="kw">const</span> lib_path: std.Build.LazyPath = .<span class="op">{</span></span>
<span id="cb26-2"><a href="#cb26-2" aria-hidden="true" tabindex="-1"></a>    .cwd_relative = <span class="st">"/usr/local/lib/"</span></span>
<span id="cb26-3"><a href="#cb26-3" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span>
<span id="cb26-4"><a href="#cb26-4" aria-hidden="true" tabindex="-1"></a>lib.root_module.addLibraryPath(lib_path);</span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
</div>
</section>
<section id="sec-include-paths" class="level3" data-number="9.11.5">
<h3 data-number="9.11.5" class="anchored" data-anchor-id="sec-include-paths"><span class="header-section-number">9.11.5</span> Adding include paths</h3>
<p>The preprocessor search path is a popular concept from the C community, but it’s also known by many C programmers as “include paths”, because the paths in this “search path” relate to the <code>#include</code> statements found in the C files.</p>
<p>Include paths are similar to library paths. They are a set of pre-defined places in your computer where the C compiler will look for files during the compilation process. But instead of looking for library files, the include paths are places where the compiler looks for header files included in your C source code. This is why many C programmers prefer to call these paths as the “preprocessor search path”. Because header files are processed during the preprocessor stage of the compilation process.</p>
<p>So, every header file that you include in your C source code, through a <code>#include</code> statements needs to be found somewhere, and the C compiler will search for this header file across the paths listed in this “include paths” set. Include paths are added to the compilation process through the <code>-I</code> flag.</p>
<p>In Zig, you can add new paths to this pre-defined set of paths, by using the <code>addIncludePath()</code> method from the <code>root_module</code> attribute of your target object. This method also accepts a <code>LazyPath</code> object as input.</p>
<div class="cell">
<div class="sourceCode cell-code" id="cb27"><pre class="sourceCode zig code-with-copy"><code class="sourceCode zig"><span id="cb27-1"><a href="#cb27-1" aria-hidden="true" tabindex="-1"></a><span class="kw">const</span> inc_path: std.Build.LazyPath = .<span class="op">{</span></span>
<span id="cb27-2"><a href="#cb27-2" aria-hidden="true" tabindex="-1"></a>    .path = <span class="st">"./include"</span></span>
<span id="cb27-3"><a href="#cb27-3" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span>
<span id="cb27-4"><a href="#cb27-4" aria-hidden="true" tabindex="-1"></a>lib.root_module.addIncludePath(inc_path);</span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div>
</div>


</section>
</section>
<section id="footnotes" class="footnotes footnotes-end-of-document" role="doc-endnotes">
<hr>
<ol>
<li id="fn1"><p><a href="https://ziglang.org/learn/build-system/#user-provided-options" class="uri">https://ziglang.org/learn/build-system/#user-provided-options</a><a href="#fnref1" class="footnote-back" role="doc-backlink">↩︎</a></p></li>
<li id="fn2"><p><a href="https://zig.news/xq/zig-build-explained-part-1-59lf" class="uri">https://zig.news/xq/zig-build-explained-part-1-59lf</a><a href="#fnref2" class="footnote-back" role="doc-backlink">↩︎</a></p></li>
<li id="fn3"><p><a href="https://cmake.org/cmake/help/latest/manual/cmake-buildsystem.7.html" class="uri">https://cmake.org/cmake/help/latest/manual/cmake-buildsystem.7.html</a><a href="#fnref3" class="footnote-back" role="doc-backlink">↩︎</a></p></li>
<li id="fn4"><p><a href="https://ziglang.org/learn/build-system/#handy-examples" class="uri">https://ziglang.org/learn/build-system/#handy-examples</a><a href="#fnref4" class="footnote-back" role="doc-backlink">↩︎</a></p></li>
<li id="fn5"><p><a href="https://semver.org/" class="uri">https://semver.org/</a><a href="#fnref5" class="footnote-back" role="doc-backlink">↩︎</a></p></li>
<li id="fn6"><p><a href="https://github.com/pedropark99/zig-book/blob/main/ZigExamples/build_system/build_and_run.zig" class="uri">https://github.com/pedropark99/zig-book/blob/main/ZigExamples/build_system/build_and_run.zig</a><a href="#fnref6" class="footnote-back" role="doc-backlink">↩︎</a></p></li>
<li id="fn7"><p><a href="https://github.com/pedropark99/zig-book/blob/main/ZigExamples/build_system/build_tests.zig" class="uri">https://github.com/pedropark99/zig-book/blob/main/ZigExamples/build_system/build_tests.zig</a><a href="#fnref7" class="footnote-back" role="doc-backlink">↩︎</a></p></li>
<li id="fn8"><p><a href="https://github.com/mitchellh/libxev/tree/main" class="uri">https://github.com/mitchellh/libxev/tree/main</a><a href="#fnref8" class="footnote-back" role="doc-backlink">↩︎</a></p></li>
<li id="fn9"><p><a href="https://freetype.org/" class="uri">https://freetype.org/</a><a href="#fnref9" class="footnote-back" role="doc-backlink">↩︎</a></p></li>
<li id="fn10"><p><a href="https://github.com/pedropark99/freetype-zig/tree/main" class="uri">https://github.com/pedropark99/freetype-zig/tree/main</a><a href="#fnref10" class="footnote-back" role="doc-backlink">↩︎</a></p></li>
<li id="fn11"><p><a href="https://freetype.org/" class="uri">https://freetype.org/</a><a href="#fnref11" class="footnote-back" role="doc-backlink">↩︎</a></p></li>
</ol>
</section>

</main> <!-- /main -->
<script id="quarto-html-after-body" type="application/javascript">
  window.document.addEventListener("DOMContentLoaded", function (event) {
    // Ensure there is a toggle, if there isn't float one in the top right
    if (window.document.querySelector('.quarto-color-scheme-toggle') === null) {
      const a = window.document.createElement('a');
      a.classList.add('top-right');
      a.classList.add('quarto-color-scheme-toggle');
      a.href = "";
      a.onclick = function() { try { window.quartoToggleColorScheme(); } catch {} return false; };
      const i = window.document.createElement("i");
      i.classList.add('bi');
      a.appendChild(i);
      window.document.body.appendChild(a);
    }
    setColorSchemeToggle(hasAlternateSentinel())
    const icon = "";
    const anchorJS = new window.AnchorJS();
    anchorJS.options = {
      placement: 'right',
      icon: icon
    };
    anchorJS.add('.anchored');
    const isCodeAnnotation = (el) => {
      for (const clz of el.classList) {
        if (clz.startsWith('code-annotation-')) {                     
          return true;
        }
      }
      return false;
    }
    const onCopySuccess = function(e) {
      // button target
      const button = e.trigger;
      // don't keep focus
      button.blur();
      // flash "checked"
      button.classList.add('code-copy-button-checked');
      var currentTitle = button.getAttribute("title");
      button.setAttribute("title", "Copied!");
      let tooltip;
      if (window.bootstrap) {
        button.setAttribute("data-bs-toggle", "tooltip");
        button.setAttribute("data-bs-placement", "left");
        button.setAttribute("data-bs-title", "Copied!");
        tooltip = new bootstrap.Tooltip(button, 
          { trigger: "manual", 
            customClass: "code-copy-button-tooltip",
            offset: [0, -8]});
        tooltip.show();    
      }
      setTimeout(function() {
        if (tooltip) {
          tooltip.hide();
          button.removeAttribute("data-bs-title");
          button.removeAttribute("data-bs-toggle");
          button.removeAttribute("data-bs-placement");
        }
        button.setAttribute("title", currentTitle);
        button.classList.remove('code-copy-button-checked');
      }, 1000);
      // clear code selection
      e.clearSelection();
    }
    const getTextToCopy = function(trigger) {
        const codeEl = trigger.previousElementSibling.cloneNode(true);
        for (const childEl of codeEl.children) {
          if (isCodeAnnotation(childEl)) {
            childEl.remove();
          }
        }
        return codeEl.innerText;
    }
    const clipboard = new window.ClipboardJS('.code-copy-button:not([data-in-quarto-modal])', {
      text: getTextToCopy
    });
    clipboard.on('success', onCopySuccess);
    if (window.document.getElementById('quarto-embedded-source-code-modal')) {
      const clipboardModal = new window.ClipboardJS('.code-copy-button[data-in-quarto-modal]', {
        text: getTextToCopy,
        container: window.document.getElementById('quarto-embedded-source-code-modal')
      });
      clipboardModal.on('success', onCopySuccess);
    }
      var localhostRegex = new RegExp(/^(?:http|https):\/\/localhost\:?[0-9]*\//);
      var mailtoRegex = new RegExp(/^mailto:/);
        var filterRegex = new RegExp('/' + window.location.host + '/');
      var isInternal = (href) => {
          return filterRegex.test(href) || localhostRegex.test(href) || mailtoRegex.test(href);
      }
      // Inspect non-navigation links and adorn them if external
     var links = window.document.querySelectorAll('a[href]:not(.nav-link):not(.navbar-brand):not(.toc-action):not(.sidebar-link):not(.sidebar-item-toggle):not(.pagination-link):not(.no-external):not([aria-hidden]):not(.dropdown-item):not(.quarto-navigation-tool):not(.about-link)');
      for (var i=0; i<links.length; i++) {
        const link = links[i];
        if (!isInternal(link.href)) {
          // undo the damage that might have been done by quarto-nav.js in the case of
          // links that we want to consider external
          if (link.dataset.originalHref !== undefined) {
            link.href = link.dataset.originalHref;
          }
        }
      }
    function tippyHover(el, contentFn, onTriggerFn, onUntriggerFn) {
      const config = {
        allowHTML: true,
        maxWidth: 500,
        delay: 100,
        arrow: false,
        appendTo: function(el) {
            return el.parentElement;
        },
        interactive: true,
        interactiveBorder: 10,
        theme: 'quarto',
        placement: 'bottom-start',
      };
      if (contentFn) {
        config.content = contentFn;
      }
      if (onTriggerFn) {
        config.onTrigger = onTriggerFn;
      }
      if (onUntriggerFn) {
        config.onUntrigger = onUntriggerFn;
      }
      window.tippy(el, config); 
    }
    const noterefs = window.document.querySelectorAll('a[role="doc-noteref"]');
    for (var i=0; i<noterefs.length; i++) {
      const ref = noterefs[i];
      tippyHover(ref, function() {
        // use id or data attribute instead here
        let href = ref.getAttribute('data-footnote-href') || ref.getAttribute('href');
        try { href = new URL(href).hash; } catch {}
        const id = href.replace(/^#\/?/, "");
        const note = window.document.getElementById(id);
        if (note) {
          return note.innerHTML;
        } else {
          return "";
        }
      });
    }
    const xrefs = window.document.querySelectorAll('a.quarto-xref');
    const processXRef = (id, note) => {
      // Strip column container classes
      const stripColumnClz = (el) => {
        el.classList.remove("page-full", "page-columns");
        if (el.children) {
          for (const child of el.children) {
            stripColumnClz(child);
          }
        }
      }
      stripColumnClz(note)
      if (id === null || id.startsWith('sec-')) {
        // Special case sections, only their first couple elements
        const container = document.createElement("div");
        if (note.children && note.children.length > 2) {
          container.appendChild(note.children[0].cloneNode(true));
          for (let i = 1; i < note.children.length; i++) {
            const child = note.children[i];
            if (child.tagName === "P" && child.innerText === "") {
              continue;
            } else {
              container.appendChild(child.cloneNode(true));
              break;
            }
          }
          if (window.Quarto?.typesetMath) {
            window.Quarto.typesetMath(container);
          }
          return container.innerHTML
        } else {
          if (window.Quarto?.typesetMath) {
            window.Quarto.typesetMath(note);
          }
          return note.innerHTML;
        }
      } else {
        // Remove any anchor links if they are present
        const anchorLink = note.querySelector('a.anchorjs-link');
        if (anchorLink) {
          anchorLink.remove();
        }
        if (window.Quarto?.typesetMath) {
          window.Quarto.typesetMath(note);
        }
        if (note.classList.contains("callout")) {
          return note.outerHTML;
        } else {
          return note.innerHTML;
        }
      }
    }
    for (var i=0; i<xrefs.length; i++) {
      const xref = xrefs[i];
      tippyHover(xref, undefined, function(instance) {
        instance.disable();
        let url = xref.getAttribute('href');
        let hash = undefined; 
        if (url.startsWith('#')) {
          hash = url;
        } else {
          try { hash = new URL(url).hash; } catch {}
        }
        if (hash) {
          const id = hash.replace(/^#\/?/, "");
          const note = window.document.getElementById(id);
          if (note !== null) {
            try {
              const html = processXRef(id, note.cloneNode(true));
              instance.setContent(html);
            } finally {
              instance.enable();
              instance.show();
            }
          } else {
            // See if we can fetch this
            fetch(url.split('#')[0])
            .then(res => res.text())
            .then(html => {
              const parser = new DOMParser();
              const htmlDoc = parser.parseFromString(html, "text/html");
              const note = htmlDoc.getElementById(id);
              if (note !== null) {
                const html = processXRef(id, note);
                instance.setContent(html);
              } 
            }).finally(() => {
              instance.enable();
              instance.show();
            });
          }
        } else {
          // See if we can fetch a full url (with no hash to target)
          // This is a special case and we should probably do some content thinning / targeting
          fetch(url)
          .then(res => res.text())
          .then(html => {
            const parser = new DOMParser();
            const htmlDoc = parser.parseFromString(html, "text/html");
            const note = htmlDoc.querySelector('main.content');
            if (note !== null) {
              // This should only happen for chapter cross references
              // (since there is no id in the URL)
              // remove the first header
              if (note.children.length > 0 && note.children[0].tagName === "HEADER") {
                note.children[0].remove();
              }
              const html = processXRef(null, note);
              instance.setContent(html);
            } 
          }).finally(() => {
            instance.enable();
            instance.show();
          });
        }
      }, function(instance) {
      });
    }
        let selectedAnnoteEl;
        const selectorForAnnotation = ( cell, annotation) => {
          let cellAttr = 'data-code-cell="' + cell + '"';
          let lineAttr = 'data-code-annotation="' +  annotation + '"';
          const selector = 'span[' + cellAttr + '][' + lineAttr + ']';
          return selector;
        }
        const selectCodeLines = (annoteEl) => {
          const doc = window.document;
          const targetCell = annoteEl.getAttribute("data-target-cell");
          const targetAnnotation = annoteEl.getAttribute("data-target-annotation");
          const annoteSpan = window.document.querySelector(selectorForAnnotation(targetCell, targetAnnotation));
          const lines = annoteSpan.getAttribute("data-code-lines").split(",");
          const lineIds = lines.map((line) => {
            return targetCell + "-" + line;
          })
          let top = null;
          let height = null;
          let parent = null;
          if (lineIds.length > 0) {
              //compute the position of the single el (top and bottom and make a div)
              const el = window.document.getElementById(lineIds[0]);
              top = el.offsetTop;
              height = el.offsetHeight;
              parent = el.parentElement.parentElement;
            if (lineIds.length > 1) {
              const lastEl = window.document.getElementById(lineIds[lineIds.length - 1]);
              const bottom = lastEl.offsetTop + lastEl.offsetHeight;
              height = bottom - top;
            }
            if (top !== null && height !== null && parent !== null) {
              // cook up a div (if necessary) and position it 
              let div = window.document.getElementById("code-annotation-line-highlight");
              if (div === null) {
                div = window.document.createElement("div");
                div.setAttribute("id", "code-annotation-line-highlight");
                div.style.position = 'absolute';
                parent.appendChild(div);
              }
              div.style.top = top - 2 + "px";
              div.style.height = height + 4 + "px";
              div.style.left = 0;
              let gutterDiv = window.document.getElementById("code-annotation-line-highlight-gutter");
              if (gutterDiv === null) {
                gutterDiv = window.document.createElement("div");
                gutterDiv.setAttribute("id", "code-annotation-line-highlight-gutter");
                gutterDiv.style.position = 'absolute';
                const codeCell = window.document.getElementById(targetCell);
                const gutter = codeCell.querySelector('.code-annotation-gutter');
                gutter.appendChild(gutterDiv);
              }
              gutterDiv.style.top = top - 2 + "px";
              gutterDiv.style.height = height + 4 + "px";
            }
            selectedAnnoteEl = annoteEl;
          }
        };
        const unselectCodeLines = () => {
          const elementsIds = ["code-annotation-line-highlight", "code-annotation-line-highlight-gutter"];
          elementsIds.forEach((elId) => {
            const div = window.document.getElementById(elId);
            if (div) {
              div.remove();
            }
          });
          selectedAnnoteEl = undefined;
        };
          // Handle positioning of the toggle
      window.addEventListener(
        "resize",
        throttle(() => {
          elRect = undefined;
          if (selectedAnnoteEl) {
            selectCodeLines(selectedAnnoteEl);
          }
        }, 10)
      );
      function throttle(fn, ms) {
      let throttle = false;
      let timer;
        return (...args) => {
          if(!throttle) { // first call gets through
              fn.apply(this, args);
              throttle = true;
          } else { // all the others get throttled
              if(timer) clearTimeout(timer); // cancel #2
              timer = setTimeout(() => {
                fn.apply(this, args);
                timer = throttle = false;
              }, ms);
          }
        };
      }
        // Attach click handler to the DT
        const annoteDls = window.document.querySelectorAll('dt[data-target-cell]');
        for (const annoteDlNode of annoteDls) {
          annoteDlNode.addEventListener('click', (event) => {
            const clickedEl = event.target;
            if (clickedEl !== selectedAnnoteEl) {
              unselectCodeLines();
              const activeEl = window.document.querySelector('dt[data-target-cell].code-annotation-active');
              if (activeEl) {
                activeEl.classList.remove('code-annotation-active');
              }
              selectCodeLines(clickedEl);
              clickedEl.classList.add('code-annotation-active');
            } else {
              // Unselect the line
              unselectCodeLines();
              clickedEl.classList.remove('code-annotation-active');
            }
          });
        }
    const findCites = (el) => {
      const parentEl = el.parentElement;
      if (parentEl) {
        const cites = parentEl.dataset.cites;
        if (cites) {
          return {
            el,
            cites: cites.split(' ')
          };
        } else {
          return findCites(el.parentElement)
        }
      } else {
        return undefined;
      }
    };
    var bibliorefs = window.document.querySelectorAll('a[role="doc-biblioref"]');
    for (var i=0; i<bibliorefs.length; i++) {
      const ref = bibliorefs[i];
      const citeInfo = findCites(ref);
      if (citeInfo) {
        tippyHover(citeInfo.el, function() {
          var popup = window.document.createElement('div');
          citeInfo.cites.forEach(function(cite) {
            var citeDiv = window.document.createElement('div');
            citeDiv.classList.add('hanging-indent');
            citeDiv.classList.add('csl-entry');
            var biblioDiv = window.document.getElementById('ref-' + cite);
            if (biblioDiv) {
              citeDiv.innerHTML = biblioDiv.innerHTML;
            }
            popup.appendChild(citeDiv);
          });
          return popup.innerHTML;
        });
      }
    }
  });
  </script>
<nav class="page-navigation">
  <div class="nav-page nav-page-previous">
      <a href="../Chapters/03-unittests.html" class="pagination-link" aria-label="Unit tests">
        <i class="bi bi-arrow-left-short"></i> <span class="nav-page-text"><span class="chapter-number">8</span>&nbsp; <span class="chapter-title">Unit tests</span></span>
      </a>          
  </div>
  <div class="nav-page nav-page-next">
      <a href="../Chapters/09-error-handling.html" class="pagination-link" aria-label="Error handling and unions">
        <span class="nav-page-text"><span class="chapter-number">10</span>&nbsp; <span class="chapter-title">Error handling and unions</span></span> <i class="bi bi-arrow-right-short"></i>
      </a>
  </div>
</nav>
</div> <!-- /content -->




</body></html>